"}},"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/nginx\"}}})":{"__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/nginx\"}}})":{"__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","de-DE"]},"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-1746693049844":{"__typename":"CachedAsset","id":"pages-1746693049844","value":[{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetInvolved.MvpProgram","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved/mvp-program","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"BlogViewAllPostsPage","type":"BLOG","urlPath":"/category/:categoryId/blog/:boardId/all-posts/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"CasePortalPage","type":"CASE_PORTAL","urlPath":"/caseportal","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"CreateGroupHubPage","type":"GROUP_HUB","urlPath":"/groups/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"CaseViewPage","type":"CASE_DETAILS","urlPath":"/case/:caseId/:caseNumber","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"InboxPage","type":"COMMUNITY","urlPath":"/inbox","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetInvolved.AdvocacyProgram","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved/advocacy-program","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetHelp.NonCustomer","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/non-customer","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HelpFAQPage","type":"COMMUNITY","urlPath":"/help","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetHelp.F5Customer","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/f5-customer","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"IdeaMessagePage","type":"IDEA_POST","urlPath":"/idea/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"IdeaViewAllIdeasPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId/all-ideas/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"LoginPage","type":"USER","urlPath":"/signin","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"BlogPostPage","type":"BLOG","urlPath":"/category/:categoryId/blogs/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetInvolved","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"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":1746693049844,"localOverride":null,"page":{"id":"ThemeEditorPage","type":"COMMUNITY","urlPath":"/designer/themes","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"TkbViewAllArticlesPage","type":"TKB","urlPath":"/category/:categoryId/kb/:boardId/all-articles/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"OccasionEditPage","type":"EVENT","urlPath":"/event/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"OAuthAuthorizationAllowPage","type":"USER","urlPath":"/auth/authorize/allow","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"PageEditorPage","type":"COMMUNITY","urlPath":"/designer/pages","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"PostPage","type":"COMMUNITY","urlPath":"/category/:categoryId/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ForumBoardPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"TkbBoardPage","type":"TKB","urlPath":"/category/:categoryId/kb/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"EventPostPage","type":"EVENT","urlPath":"/category/:categoryId/events/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"UserBadgesPage","type":"COMMUNITY","urlPath":"/users/:login/:userId/badges","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"GroupHubMembershipAction","type":"GROUP_HUB","urlPath":"/membership/join/:nodeId/:membershipType","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"MaintenancePage","type":"COMMUNITY","urlPath":"/maintenance","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"IdeaReplyPage","type":"IDEA_REPLY","urlPath":"/idea/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"UserSettingsPage","type":"USER","urlPath":"/mysettings/:userSettingsTab","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"GroupHubsPage","type":"GROUP_HUB","urlPath":"/groups","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ForumPostPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"OccasionRsvpActionPage","type":"OCCASION","urlPath":"/event/:boardId/:messageSubject/:messageId/rsvp/:responseType","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"VerifyUserEmailPage","type":"USER","urlPath":"/verifyemail/:userId/:verifyEmailToken","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"AllOccasionsPage","type":"OCCASION","urlPath":"/category/:categoryId/events/:boardId/all-events/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"EventBoardPage","type":"EVENT","urlPath":"/category/:categoryId/events/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"TkbReplyPage","type":"TKB_REPLY","urlPath":"/kb/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"IdeaBoardPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"CommunityGuideLinesPage","type":"COMMUNITY","urlPath":"/communityguidelines","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"CaseCreatePage","type":"SALESFORCE_CASE_CREATION","urlPath":"/caseportal/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"TkbEditPage","type":"TKB","urlPath":"/kb/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ForgotPasswordPage","type":"USER","urlPath":"/forgotpassword","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"IdeaEditPage","type":"IDEA","urlPath":"/idea/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"TagPage","type":"COMMUNITY","urlPath":"/tag/:tagName","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"BlogBoardPage","type":"BLOG","urlPath":"/category/:categoryId/blog/:boardId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"OccasionMessagePage","type":"OCCASION_TOPIC","urlPath":"/event/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ManageContentPage","type":"COMMUNITY","urlPath":"/managecontent","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ClosedMembershipNodeNonMembersPage","type":"GROUP_HUB","urlPath":"/closedgroup/:groupHubId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetHelp.Community","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/community","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"CommunityPage","type":"COMMUNITY","urlPath":"/","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetInvolved.ContributeCode","type":"COMMUNITY","urlPath":"/c/how-do-i/get-involved/contribute-code","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ForumMessagePage","type":"FORUM_TOPIC","urlPath":"/discussions/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"IdeaPostPage","type":"IDEA","urlPath":"/category/:categoryId/ideas/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"BlogMessagePage","type":"BLOG_ARTICLE","urlPath":"/blog/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"RegistrationPage","type":"USER","urlPath":"/register","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"EditGroupHubPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ForumEditPage","type":"FORUM","urlPath":"/discussions/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ResetPasswordPage","type":"USER","urlPath":"/resetpassword/:userId/:resetPasswordToken","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"TkbMessagePage","type":"TKB_ARTICLE","urlPath":"/kb/:boardId/:messageSubject/:messageId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.Learn.AboutIrules","type":"COMMUNITY","urlPath":"/c/how-do-i/learn/about-irules","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"BlogEditPage","type":"BLOG","urlPath":"/blog/:boardId/:messageSubject/:messageId/edit","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetHelp.F5Support","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/f5-support","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ManageUsersPage","type":"USER","urlPath":"/users/manage/:tab?/:manageUsersTab?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ForumReplyPage","type":"FORUM_REPLY","urlPath":"/discussions/:boardId/:messageSubject/:messageId/replies/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"PrivacyPolicyPage","type":"COMMUNITY","urlPath":"/privacypolicy","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"NotificationPage","type":"COMMUNITY","urlPath":"/notifications","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"UserPage","type":"USER","urlPath":"/users/:login/:userId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HealthCheckPage","type":"COMMUNITY","urlPath":"/health","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"OccasionReplyPage","type":"OCCASION_REPLY","urlPath":"/event/:boardId/:messageSubject/:messageId/comments/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ManageMembersPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/manage/:tab?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"SearchResultsPage","type":"COMMUNITY","urlPath":"/search","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"BlogReplyPage","type":"BLOG_REPLY","urlPath":"/blog/:boardId/:messageSubject/:messageId/replies/:replyId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"GroupHubPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"TermsOfServicePage","type":"COMMUNITY","urlPath":"/termsofservice","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetHelp","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"HowDoI.GetHelp.SecurityIncident","type":"COMMUNITY","urlPath":"/c/how-do-i/get-help/security-incident","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"CategoryPage","type":"CATEGORY","urlPath":"/category/:categoryId","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"ForumViewAllTopicsPage","type":"FORUM","urlPath":"/category/:categoryId/discussions/:boardId/all-topics/(/:after|/:before)?","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"TkbPostPage","type":"TKB","urlPath":"/category/:categoryId/kbs/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"localOverride":null,"page":{"id":"GroupHubPostPage","type":"GROUP_HUB","urlPath":"/group/:groupHubId/:boardId/create","__typename":"PageDescriptor"},"__typename":"PageResource"},{"lastUpdatedTime":1746693049844,"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-1746691645737":{"__typename":"CachedAsset","id":"theme:customTheme1-1746691645737","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},"CachedAsset:quilt:f5.prod:pages/tags/TagPage:community:zihoc95639-1746691643981":{"__typename":"CachedAsset","id":"quilt:f5.prod:pages/tags/TagPage:community:zihoc95639-1746691643981","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:1746691591040":{"__typename":"CachedAsset","id":"quiltWrapper:f5.prod:Common:1746691591040","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-1746691662365":{"__typename":"CachedAsset","id":"component:custom.widget.GainsightShared-en-us-1746691662365","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-1746691662365":{"__typename":"CachedAsset","id":"component:custom.widget.Beta_MetaNav-en-us-1746691662365","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-1746691662365":{"__typename":"CachedAsset","id":"component:custom.widget.Beta_Footer-en-us-1746691662365","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-1746691662365":{"__typename":"CachedAsset","id":"component:custom.widget.Tag_Manager_Helper-en-us-1746691662365","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-1746691662365":{"__typename":"CachedAsset","id":"component:custom.widget.Consent_Blackbar-en-us-1746691662365","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}},"displayId":"Forums"},"Forum:board:TechnicalForum":{"__typename":"Forum","id":"board:TechnicalForum","forumPolicies":{"__typename":"ForumPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"displayId":"TechnicalForum","nodeType":"board","conversationStyle":"FORUM","title":"Technical Forum","shortTitle":"Technical Forum","parent":{"__ref":"Category:category:Forums"}},"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}},"displayId":"Articles"},"Tkb:board:TechnicalArticles":{"__typename":"Tkb","id":"board:TechnicalArticles","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"displayId":"TechnicalArticles","nodeType":"board","conversationStyle":"TKB","title":"Technical Articles","shortTitle":"Technical Articles","parent":{"__ref":"Category:category:Articles"}},"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}}},"Category:category:CrowdSRC":{"__typename":"Category","id":"category:CrowdSRC","categoryPolicies":{"__typename":"CategoryPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}}},"Tkb:board:codeshare":{"__typename":"Tkb","id":"board:codeshare","tkbPolicies":{"__typename":"TkbPolicies","canReadNode":{"__typename":"PolicyResult","failureReason":null}},"boardPolicies":{"__typename":"BoardPolicies","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:296398":{"__typename":"Conversation","id":"conversation:296398","topic":{"__typename":"ForumTopicMessage","uid":296398},"lastPostingActivityTime":"2023-06-07T15:10:51.264-07:00","solved":false},"User:user:418967":{"__typename":"User","uid":418967,"login":"michaelgardner","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:418967"},"ForumTopicMessage:message:296398":{"__typename":"ForumTopicMessage","subject":"How to rewrite a path to a backend service dropping the prefix and passing the remaining path?","conversation":{"__ref":"Conversation:conversation:296398"},"id":"message:296398","revisionNum":2,"uid":296398,"depth":0,"board":{"__ref":"Forum:board:TechnicalForum"},"author":{"__ref":"User:user:418967"},"metrics":{"__typename":"MessageMetrics","views":19799},"postTime":"2022-06-02T15:34:33.246-07:00","lastPublishTime":"2022-06-02T22:57:23.764-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Hello, I am not sure whether my posting is appropriate in this area, so please delete it if there is a violation of posting rules... \n This must be a common task, but I cannot figure out how to do the following fanout rewrite in our nginx ingress: http://abcccc.com/httpbin/anything -> /anything (the httpbin backend service) \n \n When I create the following ingress with a path of '/' and send the query, I receive a proper response.\n\ncurl -I -k http://abczzz.com/anything\n\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n name: mikie-ingress\n namespace: mikie\nspec:\n ingressClassName: nginx\n rules:\n - host: abczzz.com\n http:\n paths:\n - path: / \n pathType: Prefix\n backend:\n service:\n name: httpbin-service\n port:\n number: 8999 \n \n \n \n What I really need is to be able to redirect to different services off of this single host, so I changed the ingress to the following, but the query always fails with a 404. Basically, I want the /httpbin to disappear and pass the path onto the backend service, httpbin.\n\ncurl -I -k http://abczzz.com/httpbin/anything\n\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n name: mikie-ingress\n namespace: mikie\n annotations:\n nginx.ingress.kubernetes.io/rewrite-target: /$2\nspec:\n ingressClassName: nginx\n rules:\n - host: abczzz.com\n http:\n paths:\n - path: /httpbin(/|$)(.*)\n pathType: Prefix\n backend:\n service:\n name: httpbin-service\n port:\n number: 8999 \n \n Thank you for your time and interest, \n Mike \n ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"1755","kudosSumWeight":0,"repliesCount":15,"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:303654":{"__typename":"Conversation","id":"conversation:303654","topic":{"__typename":"ForumTopicMessage","uid":303654},"lastPostingActivityTime":"2023-08-26T22:22:05.546-07:00","solved":false},"User:user:420728":{"__typename":"User","uid":420728,"login":"mangoo","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/m_assets/avatars/default/avatar-10.svg?time=0"},"id":"user:420728"},"ForumTopicMessage:message:303654":{"__typename":"ForumTopicMessage","subject":"does nginx (1.20 or newer) re-resolve DNS for proxy_pass?","conversation":{"__ref":"Conversation:conversation:303654"},"id":"message:303654","revisionNum":2,"uid":303654,"depth":0,"board":{"__ref":"Forum:board:TechnicalForum"},"author":{"__ref":"User:user:420728"},"metrics":{"__typename":"MessageMetrics","views":13099},"postTime":"2022-11-01T14:47:37.621-07:00","lastPublishTime":"2022-11-01T15:42:40.189-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Consider this nginx config snippet: location ^~ /_example/ { proxy_pass https://example.com/_example/; proxy_set_header Host my-site; } Assuming \"example.com\" DNS TTL is set to 60 seconds - will nginx re-resolve DNS after 60 seconds? Or does it only resolve the name on startup? I'm finding different info around the internet: - it will re-resolve only in the commercial nginx plus - it will re-resolve only in newer nginx releases; in older ones, one need to make some workarounds - it will only resolve once on startup and never again ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"768","kudosSumWeight":0,"repliesCount":5,"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:312686":{"__typename":"Conversation","id":"conversation:312686","topic":{"__typename":"TkbTopicMessage","uid":312686},"lastPostingActivityTime":"2025-04-25T06:27:38.282-07:00","solved":false},"User:user:242856":{"__typename":"User","uid":242856,"login":"MichaelOLeary","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/images/dS0yNDI4NTYtMjA2NzVpMjAwQzU1OUQzMEFFMDM2RQ"},"id":"user:242856"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMTI2ODYtMjMzMDFpREY2OTdGMDFBRjk4QzBGNA?revision=16\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMTI2ODYtMjMzMDFpREY2OTdGMDFBRjk4QzBGNA?revision=16","title":"jwt-annotated.png","associationType":"BODY","width":2048,"height":696,"altText":null},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMTI2ODYtMjMyMTBpMEQ4Q0Q2OEVFNUQ5NDYwMQ?revision=16\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMTI2ODYtMjMyMTBpMEQ4Q0Q2OEVFNUQ5NDYwMQ?revision=16","title":"old_man_yells_at_k8s.png","associationType":"BODY","width":128,"height":128,"altText":null},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMTI2ODYtMjMyMTNpNTExOTczNUM5RUIxMUYwNw?revision=16\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMTI2ODYtMjMyMTNpNTExOTczNUM5RUIxMUYwNw?revision=16","title":"jwt-io-example.PNG","associationType":"BODY","width":1144,"height":904,"altText":null},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMTI2ODYtMjM4MTVpMjA3NkIxMEJCQTlGQ0I4Mg?revision=16\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMTI2ODYtMjM4MTVpMjA3NkIxMEJCQTlGQ0I4Mg?revision=16","title":"jwt-annotated-k8s.png","associationType":"BODY","width":2048,"height":696,"altText":null},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMTI2ODYtMjM5NTlpRDIwN0E5QzU0ODVGODJBMQ?revision=16\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMTI2ODYtMjM5NTlpRDIwN0E5QzU0ODVGODJBMQ?revision=16","title":"success.png","associationType":"BODY","width":1346,"height":676,"altText":null},"TkbTopicMessage:message:312686":{"__typename":"TkbTopicMessage","subject":"JWT authorization with NGINX Ingress Controller","conversation":{"__ref":"Conversation:conversation:312686"},"id":"message:312686","revisionNum":16,"uid":312686,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:242856"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":" This article discusses how to achieve JWT validation, authentication, and authorization using NGINX Plus as an Ingress Controller in Kubernetes. \n ","introduction":"","metrics":{"__typename":"MessageMetrics","views":6899},"postTime":"2023-07-14T05:00:00.126-07:00","lastPublishTime":"2023-07-14T05:00:00.126-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" \n Summary \n JWT validation, authentication, and authorization using NGINX Plus is a great method for offloading JWT authentication at a proxy before your web application and API server receives a request. This article discusses how to achieve the same configuration when NGINX Plus is running as an Ingress Controller in Kubernetes (K8s). \n Introduction \n I've had two customers with similar requirements recently, and after searching the Internet and not finding any documentation on how to configure this in K8s, this article was born. I'll start with my customers' requirements, and then show how to achieve their requirements in K8s. \n Requirements \n In the cases of both of my customers, they had an external system that would issue a JWT to a client. That JWT would then be presented by the client to NGINX. Both customers wanted to verify the JWT, extract arbitrary claims, and forward the values of those claims as headers to the upstream servers. One of them wanted to also allow/disallow traffic based on whether the user was a member of a certain group, and the other customer wanted to insert a cookie in the request to the web server that contained some of the values extracted from the JWT claims. So we'll perform both of those things with our example today. \n To summarize, the requirements from my customers were to: \n \n Validate the signed JWT presented by a client \n Extract some of the values of the claims in the JWT \n Insert a request header that contained a value of one of these claims \n Insert a request header that contained all values from a claim that was an array (groups). \n Allow/disallow access based on the value of one of these claims \n \n \n \n NGINX Plus and the Kubernetes requirement \n Firstly, why NGINX Plus and not open source NGINX? Simple: JWT authentication is a feature that comes with NGINX Plus. Open source does not have this feature. \n Next, why K8s? My customers wanted to use NGINX Plus as an Ingress Controller and apply JWT auth there, as opposed to an installation of NGINX Plus on, for example, a Linux VM or in a standalone container. This was a challenge, and the reason behind this article. We achieve this functionality using the tools that K8s provides, mainly ConfigMaps and CRD's. \n \n JWT authentication in NGINX (outside of K8s) \n The official documentation is Setting up JWT Authentication | NGINX Plus, but I leaned heavily on two very good articles with examples from Liam Crilly and Alan Murphy. Liam's example uses JWT's for logging and rate limiting. Alan's example performs authorization (allows access to a site only if the JWT claim of uid is 222). Either of these two articles should be enough for anyone looking to perform JWT auth using NGINX Plus outside of K8s. \n Solution for JWT auth using NGINX Ingress Controller \n NGINX Ingress Controller is an implementation of a Kubernetes Ingress Controller for NGINX and NGINX Plus. But you don't configure NGINX with typical config files as outlined in the previously linked articles. Rather, you configure NGINX with K8s resources. \n Which resources in K8s? Traditionally it was an Ingress resource, optionally with annotations, and a ConfigMap. These resources would be monitored by NGINX I.C. and then NGINX would be configured based on the values in these resources. \n As an alternative to the Ingress, NGINX Ingress Controller supports CRD's, two of which are the VirtualServer and VirtualServerRoute resources. They enable use cases not supported with the Ingress resource, such as traffic splitting and advanced content-based routing. Since CRD's are newer, I'll demonstrate this solution using those. \n My JWT \n This is a JWT I generated using https://jwt.io. \n The payload of this JWT, which is the section containing the claims I am interested in, is below. Note there are multiple claims. One of them, groups, is an array, and the others are strings. The exp claim is a reserved claim with NumericDate value (epoch time, extra points if you can tell me what date is represented by 1924991999 ). \n { \"exp\": \"1924991999\", \"name\": \"Michael O'Leary\", \"groups\": [ \"F5Employees\", \"DevCentralAuthors\" ] } \n You can see from my screenshot that the secret for the signature of this JWT is nginx123. This is something NGINX will need to know if we want to validate the signature of the JWT, so keep this in mind for later. \n The base64 encoded value of this JWT is eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIxOTI0OTkxOTk5IiwibmFtZSI6Ik1pY2hhZWwgTydMZWFyeSIsImdyb3VwcyI6WyJGNUVtcGxveWVlcyIsIkRldkNlbnRyYWxBdXRob3JzIl19.blqHw-gRXoPQfAtPgyPuFOozUp-MZWmpCXfQtkIJCFo \n Solving for our requirements \n Non-K8s implementations \n As you can see from Liam's example and Alan's example, use the following lines in NGINX config to set up JWT auth. \n \n In the http context, we'll add a map directive. This creates a new variable ($valid_user) whose value depends on values of one or more of the source variables specified in the first parameter. \n Because one of our claims (groups) is an array, we also need to add the directive auth_jwt_claim_set which will set a variable to hold the value of a claim. We don't need to do this for each claim, but for values that are an array, the variable keeps a list of array elements separated by commas. map $jwt_claim_name $valid_user { \n \"Michael O'Leary\" 1; \n }\nauth_jwt_claim_set $jwt_groups groups; # this translates the array value into a comma-separated single string\n \n in the location context, you need to add a few lines, depending on what you're looking to achieve auth_jwt \"hello\";\nauth_jwt_key_file /etc/nginx/jwt_secret.jwk ;\nproxy_set_header name $jwt_claim_name ;\nproxy_set_header groups $jwt_groups ;\nauth_jwt_require $valid_user; \n given the config above, create a file at /etc/nginx/jwt_scret.jwk with this content. Note that bmdpbngxMjM is the base64-encoded value for nginx123 . {\"keys\":\n [{\n \"k\":\"bmdpbngxMjM\",\n \"kty\":\"oct\"\n }]\n} \n \n K8s implementation \n Here's how to do the same, using K8s resources. I will heavily comment a few lines for the sake of explaining their importance. \n My demo app is \"demo.my-f5.com\" where \"/headers\" is a page that displays all request headers received by the server. I want to only allow authorized users (those with the name Michael O'Leary) to see the \"/headers\" location, and I also want to add two headers to these requests: X-jwt-claim-name and X-jwt-claim-groups. The values of these will come from the JWT. \n Firstly, we'll use a VirtualServer CRD, which roughly translates to a NGINX server context. Here is an example of my VirtualServer CRD. \n apiVersion: k8s.nginx.org/v1\nkind: VirtualServer\nmetadata:\n name: demo\n namespace: f5demoapp\nspec:\n host: demo.my-f5.com\n upstreams:\n - name: demo\n service: f5-demo-httpd\n port: 8080\n routes:\n - path: /\n action:\n proxy:\n upstream: demo\n - path: /headers\n route: headers # this line tells NGINX to expect a VirtualServerRoute called headers and that it should include a location for /headers. This links our VirtualServer and our VirtualServerRoute \n We'll also use a VirtualServerRoute CRD, which roughly translates to a NGINX location context. Here is an example: \n apiVersion: k8s.nginx.org/v1\nkind: VirtualServerRoute\nmetadata:\n name: headers\n namespace: f5demoapp\nspec:\n host: demo.my-f5.com\n upstreams:\n - name: demo\n service: f5-demo-httpd\n port: 8080\n subroutes:\n - path: /headers\n policies:\n - name: jwtpolicy\n action:\n proxy:\n upstream: demo\n requestHeaders:\n set:\n - name: X-jwt-claim-name\n value: ${jwt_claim_name}\n location-snippets: | \n auth_jwt_require $valid_user;\n #with the line above, only requests where the JWT claim name is Michael O'Leary will be allowed to access this location. This is configured in the ConfigMap resource.\n proxy_set_header X-jwt-claim-groups $jwt_groups;\n #in the line above, I am using a location-snippet to set a header, instead of the Action.Proxy.RequestHeaders.Set.Header value. This is because the values for these headers that can be inserted using Action.Proxy.RequestHeaders.Set are limited to supported NGINX variables. https://docs.nginx.com/nginx-ingress-controller/configuration/virtualserver-and-virtualserverroute-resources/#actionproxyrequestheaderssetheader\n \n We also will use a ConfigMap, which is referenced when running the NGINX I.C. and configures NGINX, including the http context. Here is an example. \n kind: ConfigMap\napiVersion: v1\nmetadata:\n name: nginx-plus-config\n namespace: nginx-plus-ingress\ndata:\n proxy-connect-timeout: \"10s\"\n #proxy-protocol: \"True\"\n #real-ip-header: \"proxy_protocol\"\n #set-real-ip-from: \"0.0.0.0/0\"\n http-snippets: |\n map $jwt_claim_name $valid_user { \n \"Michael O'Leary\" 1; \n }\n #with the line above, we have configured $valid_user to only be 1 if the JWT claim name is Michael O'Leary. We could add additional lines to add more users also. We could also require the group claim contains a given group. This is then enforced in the VirtualServerRoute resource, linked by the $valid_user variable.\n auth_jwt_claim_set $jwt_groups groups; \n #in the line above, we are setting a variable called $jwt_groups that will be a string, separated by commas. It is populated by the groups claim from the JWT, which is an array. This variable, $jwt_groups, is used to populate a header value in the VirtualServerRoute resource. \n Notice that above we used snippets, which allow us to insert raw NGINX config into these CRD's, in cases where the YAML-based CRD doesn't meet our requirement. So, http-snippets, server-snippets, and location-snippets insert config into the http, server, the location contexts. Here's an example that uses all three. As we see from our example above, we need to use http-snippets and location-snippets. \n See above that the VirtualServerRoute referenced a CRD of type Policy to enforce JWT authentication. Here is an example of the Policy CRD that we will use. \n apiVersion: k8s.nginx.org/v1\nkind: Policy\nmetadata:\n name: jwtpolicy\n namespace: f5demoapp\nspec:\n jwt:\n secret: jwk-secret\n realm: MyDemo\n token: $cookie_jwt \n The Policy resource must reference a Secret, which must be of type: nginx.org/jwk. The following is an example of the Secret. I found this very difficult to research, so please note the value is a base64-encoded version of the secret file referenced earlier. The type of nginx.org/jwk was critical but hard for me to uncover when researching. (Although upon reading again, it is documented.) \n apiVersion: v1\nkind: Secret\nmetadata:\n name: jwk-secret\n namespace: f5demoapp\ntype: nginx.org/jwk\ndata:\n jwk: eyJrZXlzIjoKICAgIFt7CiAgICAgICAgImsiOiJibWRwYm5neE1qTSIsCiAgICAgICAgImt0eSI6Im9jdCIKICAgIH1dCn0K \n This should be all you need to achieve the same thing that Liam and Alan have documented, but in Kubernetes! Now we've configured NGINX Ingress Controller in the same was as the earlier example, but in Kubernetes: \n \n Let's revisit our requirements, now with our solutions in green: \n \n Validate the signed JWT presented by a client. Achieved by the Policy and Secret resources. \n Extract some of the values of the claims in the JWT. Done with ConfigMap and other resources. \n Insert a request header that contained a value of one of these claims. Done in VirtualServerRoute. \n Insert a request header that contained all values from a claim that was an array (groups). Also done in VirtualServerRoute, but using the location-snippets. \n Allow/disallow access based on the value of one of these claims. Done in VirtualServerRoute with auth_jwt_require and ConfigMap. \n \n I've used the files from the article to deploy the docker image at f5devcental/f5-hello-world and display these headers using the JWT from this article: \n \n Summary \n NGINX Ingress Controller using NGINX Plus allows JWT authentication for your web apps and API's running inside K8s. I hope this article helps anyone looking to achieve this. If you need help, please reach out in comments or to your F5/NGINX account team. Thanks for reading! \n Related articles \n \n Setting up JWT authentication (official docs) \n VirtualServer and VirtualServerRoute resources (official docs) \n Authenticating API Clients with JWT and NGINX Plus by Liam Crilly \n Authentication and Content-Based Routing with JWTs and NGINX Plus by Alan Murphy \n \n \n ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"12607","kudosSumWeight":1,"repliesCount":1,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMTI2ODYtMjMzMDFpREY2OTdGMDFBRjk4QzBGNA?revision=16\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDI","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMTI2ODYtMjMyMTBpMEQ4Q0Q2OEVFNUQ5NDYwMQ?revision=16\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDM","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMTI2ODYtMjMyMTNpNTExOTczNUM5RUIxMUYwNw?revision=16\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDQ","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMTI2ODYtMjM4MTVpMjA3NkIxMEJCQTlGQ0I4Mg?revision=16\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDU","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMTI2ODYtMjM5NTlpRDIwN0E5QzU0ODVGODJBMQ?revision=16\"}"}}],"totalCount":5,"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:284381":{"__typename":"Conversation","id":"conversation:284381","topic":{"__typename":"TkbTopicMessage","uid":284381},"lastPostingActivityTime":"2024-03-19T16:01:54.998-07:00","solved":false},"User:user:49688":{"__typename":"User","uid":49688,"login":"Jeff_Giroux_F5","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/images/dS00OTY4OC0xNjQzMGlBMjE3NkNDMzVDOUUwOTEw"},"id":"user:49688"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQzODEtMTkxMTlpQzVCODdDMjhCN0I3NzQ4RQ?revision=8\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQzODEtMTkxMTlpQzVCODdDMjhCN0I3NzQ4RQ?revision=8","title":"cfe-diagram.gif","associationType":"BODY","width":941,"height":728,"altText":"cfe-diagram.gif"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQzODEtNTIzMmlDMTk3QTEyQUEwQkEwMDRB?revision=8\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQzODEtNTIzMmlDMTk3QTEyQUEwQkEwMDRB?revision=8","title":"0151T000003WGPAQA4.png","associationType":"BODY","width":1295,"height":731,"altText":"0151T000003WGPAQA4.png"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQzODEtMTkxMjBpNzU1MkZBQzJEQ0VDRkNGOA?revision=8\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQzODEtMTkxMjBpNzU1MkZBQzJEQ0VDRkNGOA?revision=8","title":"regional-failover.png","associationType":"BODY","width":3516,"height":1874,"altText":"regional-failover.png"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQzODEtMTEzMDBpRjUyNDYwNDQ3N0EwNzE5QQ?revision=8\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQzODEtMTEzMDBpRjUyNDYwNDQ3N0EwNzE5QQ?revision=8","title":"0151T000003WGPKQA4.png","associationType":"BODY","width":1024,"height":502,"altText":"0151T000003WGPKQA4.png"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQzODEtMTIzN2kyMDMyM0I2NDZFN0RDQTY0?revision=8\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQzODEtMTIzN2kyMDMyM0I2NDZFN0RDQTY0?revision=8","title":"0151T000003WGOeQAO.png","associationType":"BODY","width":1024,"height":577,"altText":"0151T000003WGOeQAO.png"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQzODEtMTkxMzRpMEFBQUY5NjYyNDUwNEU5Rg?revision=8\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQzODEtMTkxMzRpMEFBQUY5NjYyNDUwNEU5Rg?revision=8","title":"public-cloud-scaling-pros-cons.png","associationType":"BODY","width":1234,"height":516,"altText":"public-cloud-scaling-pros-cons.png"},"TkbTopicMessage:message:284381":{"__typename":"TkbTopicMessage","subject":"F5 High Availability - Public Cloud Guidance","conversation":{"__ref":"Conversation:conversation:284381"},"id":"message:284381","revisionNum":8,"uid":284381,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:49688"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":5842},"postTime":"2020-05-04T11:01:37.000-07:00","lastPublishTime":"2024-03-19T16:01:54.998-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" \n This article will provide information about BIG-IP and NGINX high availability (HA) topics that should be considered when leveraging the public cloud. There are differences between on-prem and public cloud such as cloud provider L2 networking. These differences lead to challenges in how you address HA, failover time, peer setup, scaling options, and application state. \n Topics Covered: \n \n Discuss and Define HA \n Importance of Application Behavior and Traffic Sizing \n HA Capabilities of BIG-IP and NGINX \n Various HA Deployment Options (Active/Active, Active/Standby, auto scale) \n Example Customer Scenario \n \n What is High Availability? \n High availability can mean many things to different people. Depending on the application and traffic requirements, HA requires dual data paths, redundant storage, redundant power, and compute. It means the ability to survive a failure, maintenance windows should be seamless to user, and the user experience should never suffer...ever! \n Reference: https://en.wikipedia.org/wiki/High_availability \n So what should HA provide? \n \n Synchronization of configuration data to peers (ex. configs objects) \n Synchronization of application session state (ex. persistence records) \n Enable traffic to fail over to a peer \n Locally, allow clusters of devices to act and appear as one unit \n Globally, disburse traffic via DNS and routing \n \n Importance of Application Behavior and Traffic Sizing \n Let's look at a common use case... \n \"gaming app, lots of persistent connections, client needs to hit same backend throughout entire game session\" \n Session State \n The requirement of session state is common across applications using methods like HTTP cookies, F5 iRule persistence, JSessionID, IP affinity, or hash. The session type used by the application can help you decide what migration path is right for you. Is this an app more fitting for a lift-n-shift approach...Rehost? Can the app be redesigned to take advantage of all native IaaS and PaaS technologies...Refactor? \n Reference: 6 R's of a Cloud Migration \n \n Application session state allows user to have a consistent and reliable experience \n Auto scaling L7 proxies (BIG-IP or NGINX) keep track of session state \n BIG-IP can only mirror session state to next device in cluster \n NGINX can mirror state to all devices in cluster (via zone sync) \n \n Traffic Sizing \n The cloud provider does a great job with things like scaling, but there are still cloud provider limits that affect sizing and machine instance types to keep in mind. BIG-IP and NGINX are considered network virtual appliances (NVA). They carry quota limits like other cloud objects. \n \n Google GCP VPC Resource Limits \n Azure VM Flow Limits \n AWS Instance Types \n \n Unfortunately, not all limits are documented. Key metrics for L7 proxies are typically SSL stats, throughput, connection type, and connection count. Collecting these application and traffic metrics can help identify the correct instance type. We have a list of the F5 supported BIG-IP VE platforms on F5 CloudDocs. \n F5 Products and HA Capabilities \n BIG-IP HA Capabilities \n BIG-IP supports the following HA cluster configurations: \n \n Active/Active - all devices processing traffic \n Active/Standby - one device processes traffic, others wait in standby \n Configuration sync to all devices in cluster \n L3/L4 connection sharing to next device in cluster (ex. avoids re-login) \n L5-L7 state sharing to next device in cluster (ex. IP persistence, SSL persistence, iRule UIE persistence) \n \n Reference: BIG-IP High Availability Docs \n NGINX HA Capabilities \n NGINX supports the following HA cluster configurations: \n \n Active/Active - all devices processing traffic \n Active/Standby - one device processes traffic, others wait in standby \n Configuration sync to all devices in cluster \n Mirroring connections at L3/L4 not available \n Mirroring session state to ALL devices in cluster using Zone Synchronization Module (NGINX Plus R15) \n \n Reference: NGINX High Availability Docs \n HA Methods for BIG-IP \n In the following sections, I will illustrate 3 common deployment configurations for BIG-IP in public cloud. \n \n HA for BIG-IP Design #1 - Active/Standby via API \n HA for BIG-IP Design #2 - A/A or A/S via LB \n HA for BIG-IP Design #3 - Regional Failover (multi region) \n \n HA for BIG-IP Design #1 - Active/Standby via API (multi AZ) \n This failover method uses API calls to communicate with the cloud provider and move objects (IP address, routes, etc) during failover events. The F5 Cloud Failover Extension (CFE) for BIG-IP is used to declaratively configure the HA settings. \n \n Cloud provider load balancer is NOT required \n Fail over time can be SLOW! \n Only one device actively used (other device sits idle) \n Failover uses API calls to move cloud objects, times vary (see CFE Performance and Sizing) \n \n Key Findings: \n \n Google API failover times depend on number of forwarding rules \n Azure API slow to disassociate/associate IPs to NICs (remapping) \n Azure API fast when updating routes (UDR, user defined routes) \n AWS reliable with API regarding IP moves and routes \n \n Recommendations: \n \n This design with multi AZ is more preferred than single AZ \n Recommend when \"traditional\" HA cluster required or Lift-n-Shift...Rehost \n For Azure (based on my testing)... \n \n Recommend using Azure UDR versus IP failover when possible \n Look at Failover via LB example instead for Azure \n If API method required, look at DNS solutions to provide further redundancy \n \n \n \n HA for BIG-IP Design #2 - A/A or A/S via LB (multi AZ) \n \n Cloud LB health checks the BIG-IP for up/down status \n Faster failover times (depends on cloud LB health timers) \n Cloud LB allows A/A or A/S \n \n Key difference: \n \n Increased network/compute redundancy \n Cloud load balancer required \n \n Recommendations: \n \n Use \"failover via LB\" if you require faster failover times \n For Google (based on my testing)...\n \n Recommend against \"via LB\" for IPSEC traffic (Google LB not supported) \n If load balancing IPSEC, then use \"via API\" or \"via DNS\" failover methods \n \n \n \n HA for BIG-IP Design #3 - Regional Failover via DNS (multi AZ, multi region) \n \n BIG-IP VE active/active in multiple regions \n Traffic disbursed to VEs by DNS/GSLB \n DNS/GSLB intelligent health checks for the VEs \n \n Key difference: \n \n Cloud LB is not required \n DNS logic required by clients \n Orchestration required to manage configs across each BIG-IP \n BIG-IP standalone devices (no DSC cluster limitations) \n \n Recommendations: \n \n Good for apps that handle DNS resolution well upon failover events \n Recommend when cloud LB cannot handle a particular protocol \n Recommend when customer is already using DNS to direct traffic \n Recommend for applications that have been refactored to handle session state outside of BIG-IP \n Recommend for customers with in-house skillset to orchestrate (Ansible, Terraform, etc) \n \n HA Methods for NGINX \n In the following sections, I will illustrate 2 common deployment configurations for NGINX in public cloud. \n \n HA for NGINX Design #1 - Active/Standby via API \n HA for NGINX Design #2 - Auto Scale Active/Active via LB \n \n HA for NGINX Design #1 - Active/Standby via API (multi AZ) \n \n NGINX Plus required \n Cloud provider load balancer is NOT required \n Only one device actively used (other device sits idle) \n Only available in AWS currently \n \n Recommendations: \n \n Recommend when \"traditional\" HA cluster required or Lift-n-Shift...Rehost \n \n Reference: Active-Passive HA for NGINX Plus on AWS \n HA for NGINX Design #2 - Auto Scale Active/Active via LB (multi AZ) \n \n NGINX Plus required \n Cloud LB health checks the NGINX \n Faster failover times \n \n Key difference: \n \n Increased network/compute redundancy \n Cloud load balancer required \n \n Recommendations: \n \n Recommended for apps fitting a migration type of Replatform or Refactor \n \n Reference: Active-Active HA for NGINX Plus on AWS, Active-Active HA for NGINX Plus on Google \n Pros & Cons: Public Cloud Scaling Options \n Review this handy table to understand the high level pros and cons of each deployment method. \n Example Customer Scenario #1 \n As a means to make this topic a little more real, here is a common customer scenario that shows you the decisions that go into moving an application to the public cloud. Sometimes it's as easy as a lift-n-shift, other times you might need to do a little more work. In general, public cloud is not on-prem and things might need some tweaking. Hopefully this example will give you some pointers and guidance on your next app migration to the cloud. \n Current Setup: \n \n Gaming applications \n F5 Hardware BIG-IP VIRPIONs on-prem \n Two data centers for HA redundancy \n iRule heavy configuration (TLS encryption/decryption, payload inspections) \n Session Persistence = iRule Universal Persistence (UIE), and other methods \n Biggest app \n 15K SSL TPS \n 15Gbps throughput \n 2 million concurrent connections \n 300K HTTP req/sec (L7 with TLS) \n \n Requirements for Successful Cloud Migration: \n \n Support current traffic numbers \n Support future target traffic growth \n Must run in multiple geographic regions \n Maintain session state \n Must retain all iRules in use \n \n Recommended Design for Cloud Phase #1: \n \n Migration Type: Hybrid model, on-prem + cloud, and some Rehost \n Platform: BIG-IP \n Retaining iRules means BIG-IP is required \n Licensing: High Performance BIG-IP \n Unlocks additional CPU cores past 8 (up to 24) \n extra traffic and SSL processing \n Instance type: check F5 supported BIG-IP VE platforms for accelerated networking (10Gb+) \n HA method: Active/Standby and multi-region with DNS \n iRule Universal persistence only mirrors to only next device, keep cluster size to 2 \n scale horizontally via additional HA clusters and DNS \n clients pinned to a region via DNS (on-prem or public cloud) \n inside region, local proxy cluster shares state \n \n This example comes up in customer conversations often. Based on customer requirements, in-house skillset, current operational model, and time frames there is one option that is better than the rest. A second design phase lends itself to more of a Replatform or Refactor migration type. In that case, more options can be leveraged to take advantage of cloud-native features. For example, changing the application persistence type from iRule UIE to cookie would allow BIG-IP to avoid keeping track of state. Why? With cookies, the client keeps track of that session state. Client receives a cookie, passes the cookie to L7 proxy on successive requests, proxy checks cookie value, sends to backend pool member. The requirement for L7 proxy to share session state is now removed. \n Example Customer Scenario #2 \n Here is another customer scenario. This time the application is a full suite of multimedia content. In contrast to the first scenario, this one will illustrate the benefits of rearchitecting various components allowing greater flexibility when leveraging the cloud. You still must factor in-house skill set, project time frames, and other important business (and application) requirements when deciding on the best migration type. \n Current Setup: \n \n Multimedia (Gaming, Movie, TV, Music) Platform \n BIG-IP VIPRIONs using vCMP on-prem \n Two data centers for HA redundancy \n iRule heavy (Security, Traffic Manipulation, Performance) \n Biggest App: oAuth + Cassandra for token storage (entitlements) \n \n Requirements for Success Cloud Migration: \n \n Support current traffic numbers \n Elastic auto scale for seasonal growth (ex. holidays) \n VPC peering with partners (must also bypass Web Application Firewall) \n Must support current or similar traffic manipulating in data plane \n Compatibility with existing tooling used by Business \n \n Recommended Design for Cloud Phase #1: \n \n Migration Type: Repurchase, migration BIG-IP to NGINX Plus \n Platform: NGINX \n iRules converted to JS or LUA \n Licensing: NGINX Plus \n Modules: GeoIP, LUA, JavaScript \n HA method: N+1 \n Autoscaling via Native LB \n Active Health Checks \n \n This is a great example of a Repurchase in which application characteristics can allow the various teams to explore alternative cloud migration approaches. In this scenario, it describes a phase one migration of converting BIG-IP devices to NGINX Plus devices. This example assumes the BIG-IP configurations can be somewhat easily converted to NGINX Plus, and it also assumes there is available skillset and project time allocated to properly rearchitect the application where needed. \n Summary \n OK! Brains are expanding...hopefully? We learned about high availability and what that means for applications and user experience. We touched on the importance of application behavior and traffic sizing. Then we explored the various F5 products, how they handle HA, and HA designs. These recommendations are based on my own lab testing and interactions with customers. Every scenario will carry its own requirements, and all options should be carefully considered when leveraging the public cloud. Finally, we looked at a customer scenario, discussed requirements, and design proposal. Fun! \n Resources \n Read the following articles for more guidance specific to the various cloud providers. \n \n Advanced Topologies and More on Highly Available Services \n Lightboard Lessons - BIG-IP Deployments in Azure \n Google and BIG-IP Failing Faster in the Cloud \n BIG-IP VE on Public Cloud \n High-Availability Load Balancing with NGINX Plus on Google Cloud Platform \n Using AWS Quick Starts to Deploy NGINX Plus \n NGINX on Azure \n \n ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"13591","kudosSumWeight":5,"repliesCount":2,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQzODEtMTkxMTlpQzVCODdDMjhCN0I3NzQ4RQ?revision=8\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDI","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQzODEtNTIzMmlDMTk3QTEyQUEwQkEwMDRB?revision=8\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDM","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQzODEtMTkxMjBpNzU1MkZBQzJEQ0VDRkNGOA?revision=8\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDQ","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQzODEtMTEzMDBpRjUyNDYwNDQ3N0EwNzE5QQ?revision=8\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDU","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQzODEtMTIzN2kyMDMyM0I2NDZFN0RDQTY0?revision=8\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDY","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yODQzODEtMTkxMzRpMEFBQUY5NjYyNDUwNEU5Rg?revision=8\"}"}}],"totalCount":6,"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:291023":{"__typename":"Conversation","id":"conversation:291023","topic":{"__typename":"TkbTopicMessage","uid":291023},"lastPostingActivityTime":"2021-09-20T11:41:48.000-07:00","solved":false},"User:user:326558":{"__typename":"User","uid":326558,"login":"Eric_Ji","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/images/dS0zMjY1NTgtaDBOSjVu?image-coordinates=0%2C0%2C1110%2C1110"},"id":"user:326558"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yOTEwMjMtNjI5N2k2NDJBNkY1RTc4MTlGRjAy?revision=1\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yOTEwMjMtNjI5N2k2NDJBNkY1RTc4MTlGRjAy?revision=1","title":"0151T000003uvtEQAQ.png","associationType":"BODY","width":1474,"height":918,"altText":null},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yOTEwMjMtMTQwNzZpQ0NENEQ3ODAwOEM2MjQzQw?revision=1\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yOTEwMjMtMTQwNzZpQ0NENEQ3ODAwOEM2MjQzQw?revision=1","title":"0151T000003uxzOQAQ.png","associationType":"BODY","width":2750,"height":1691,"altText":null},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yOTEwMjMtNjUzNGk1NzFBQUQ5M0VBREU3MDAz?revision=1\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yOTEwMjMtNjUzNGk1NzFBQUQ5M0VBREU3MDAz?revision=1","title":"0151T000003uvtiQAA.png","associationType":"BODY","width":705,"height":450,"altText":null},"TkbTopicMessage:message:291023":{"__typename":"TkbTopicMessage","subject":"Deploying NGINX Ingress Controller with OpenShift on AWS Managed Service: ROSA","conversation":{"__ref":"Conversation:conversation:291023"},"id":"message:291023","revisionNum":1,"uid":291023,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:326558"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":5213},"postTime":"2021-09-20T11:41:48.000-07:00","lastPublishTime":"2021-09-20T11:41:48.000-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Introduction In March 2021, Amazon and Red Hat announced the General Availability of Red Hat OpenShift Service on AWS (ROSA). ROSA is a fully-managed OpenShift service, jointly managed and supported by both Red Hat and Amazon Web Services (AWS). OpenShift offers users several different deployment models. For customers that require a high degree of customization and have the skill sets to manage their environment, they can build and manage OpenShift Container Platform (OCP) on AWS. For those who want to alleviate the complexity in managing the environment and focus on their applications, they can consume OpenShift as a service, or Red Hat OpenShift Service on AWS (ROSA). The benefits of ROSA are two-fold. First, we can enjoy more simplified Kubernetes cluster creation using the familiar Red Hat OpenShift console, features, and tooling without the burden of manually scaling and managing the underlying infrastructure. Secondly, the managed service made easier with joint billing, support, and out-of-the-box integration to AWS infrastructure and services. In this article, I am exploring how to deploy an environment with NGINX Ingress Controller integrated into ROSA. Deploy Red Hat OpenShift Service on AWS (ROSA) The ROSA service may be deployed directly from the AWS console. Red Hat has done a great job in providing the instructions on creating a ROSA cluster in the Installation Guide. The guide documents the AWS prerequisites, required AWS service quotas, and configuration of your AWS accounts. We run the following commands to ensure that the prerequisites are met before installing ROSA. - Verify that my AWS account has the necessary permissions: ❯ rosa verify permissions\nI: Validating SCP policies...\nI: AWS SCP policies ok\n - Verify that my AWS account has the necessary quota to deploy a Red Hat OpenShift Service on the AWS cluster. ❯ rosa verify quota --region=us-west-2\nI: Validating AWS quota...\nI: AWS quota ok. If cluster installation fails, validate actual AWS resource usage against https://docs.openshift.com/rosa/rosa_getting_started/rosa-required-aws-service-quotas.html\n Next, I ran the following command to prepare my AWS account for cluster deployment: ❯ rosa init\nI: Logged in as 'ericji' on 'https://api.openshift.com'\nI: Validating AWS credentials...\nI: AWS credentials are valid!\nI: Validating SCP policies...\nI: AWS SCP policies ok\nI: Validating AWS quota...\nI: AWS quota ok. If cluster installation fails, validate actual AWS resource usage against https://docs.openshift.com/rosa/rosa_getting_started/rosa-required-aws-service-quotas.html\nI: Ensuring cluster administrator user 'osdCcsAdmin'...\nI: Admin user 'osdCcsAdmin' created successfully!\nI: Validating SCP policies for 'osdCcsAdmin'...\nI: AWS SCP policies ok\nI: Validating cluster creation...\nI: Cluster creation valid\nI: Verifying whether OpenShift command-line tool is available...\nI: Current OpenShift Client Version: 4.7.19\n If we were to follow their instructions to create a ROSA cluster using the rosa CLI, after about 35 minutes our deployment would produce a Red Hat OpenShift cluster along with the needed AWS components. ❯ rosa create cluster --cluster-name=eric-rosa\nI: Creating cluster 'eric-rosa'\nI: To view a list of clusters and their status, run 'rosa list clusters'\nI: Cluster 'eric-rosa' has been created.\nI: Once the cluster is installed you will need to add an Identity Provider before you can login into the cluster. See 'rosa create idp --help' for more information.\nI: To determine when your cluster is Ready, run 'rosa describe cluster -c eric-rosa'.\nI: To watch your cluster installation logs, run 'rosa logs install -c eric-rosa --watch'.\nName: eric-rosa\n…\n During the deployment, we may enter the following command to follow the OpenShift installer logs to track the progress of our cluster: > rosa logs install -c eric-rosa --watch\n After the Red Hat OpenShift Service on AWS (ROSA) cluster is created, we must configure identity providers to determine how users log in to access the cluster. What just happened? Let's review what just happened. The above installation program automatically set up the following AWS resources for the ROSA environment: AWS VPC subnets per Availability Zone (AZ). For single AZ implementations two subnets were created (one public one private) The multi-AZ implementation would make use of three Availability Zones, with a public and private subnet in each AZ (a total of six subnets). OpenShift cluster nodes (or EC2 instances) Three Master nodes were created to cater for cluster quorum and to ensure proper fail-over and resilience of OpenShift. At least two infrastructure nodes, catering for build-in OpenShift container registry, OpenShift router layer, and monitoring. Multi-AZ implementations Three Master nodes and three infrastructure nodes spread across three AZs Assuming that application workloads will also be running in all three AZs for resilience, this will deploy three Workers. This will translate to a minimum of nine EC2 instances running within the customer account. A collection of AWS Elastic Load Balancers, some of these Load balancers will provide end-user access to the application workloads running on OpenShift via the OpenShift router layer, other AWS elastic load balancers will expose endpoints used for cluster administration and management by the SRE teams. Source: https://aws.amazon.com/blogs/containers/red-hat-openshift-service-on-aws-architecture-and-networking/ Deploy NGINX Ingress Controller The NGINX Ingress Operator is a supported and certified mechanism for deploying NGINX Ingress Controller in an OpenShift environment, with point-and-click installation and automatic upgrades. It works for both the NGINX Open Source-based and NGINX Plus-based editions of NGINX Ingress Controller. In this tutorial, I’ll be deploying the NGINX Plus-based edition. Read Why You Need an Enterprise-Grade Ingress Controller on OpenShift for use cases that merit the use of this edition. If you’re not sure how these editions are different, read Wait, Which NGINX Ingress Controller for Kubernetes Am I Using? I install the NGINX Ingress Operator from the OpenShift console. There are numerous options you can set when configuring the NGINX Ingress Controller, as listed in our GitHub repo. Here is a manifest example : apiVersion: k8s.nginx.org/v1alpha1\nkind: NginxIngressController\nmetadata:\n name: my-nginx-ingress-controller\n namespace: openshift-operators\nspec:\n ingressClass: nginx\n serviceType: LoadBalancer\n nginxPlus: true\n type: deployment\n image:\n pullPolicy: Always\n repository: ericzji/nginx-plus-ingress\n tag: 1.12.0\n To verify the deployment, run the following commands in a terminal. As shown in the output, the manifest I used in the previous step deployed two replicas of the NGINX Ingress Controller and exposed them with a LoadBalancer service. ❯ oc get pods -n openshift-operators\nNAME READY STATUS RESTARTS AGE\nmy-nginx-ingress-controller-b556f8bb-bsn4k 1/1 Running 0 14m\nnginx-ingress-operator-controller-manager-7844f95d5f-pfczr 2/2 Running 0 3d5h\n \n❯ oc get svc -n openshift-operators\nNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE\nmy-nginx-ingress-controller LoadBalancer 172.30.171.237 a2b3679e50d36446d99d105d5a76d17f-1690020410.us-west-2.elb.amazonaws.com 80:30860/TCP,443:30143/TCP 25h\nnginx-ingress-operator-controller-manager-metrics-service ClusterIP 172.30.50.231 <none>\n With NGINX Ingress Controller deployed, we'll have an environment that looks like this: Post-deployment verification After the ROSA cluster was configured, I deployed an app (Hipster) in OpenShift that is exposed by NGINX Ingress Controller (by creating an Ingress resource). To use a custom hostname, it requires that we manually change your DNS record on the Internet to point to the IP address value of AWS Elastic Load Balancer. ❯ dig +short a2dc51124360841468c684127c4a8c13-808882247.us-west-2.elb.amazonaws.com\n34.209.171.103\n52.39.87.162\n35.164.231.54\n I made this DNS change (optionally, use a local host record), and we will see my demo app available on the Internet, like this: Deleting your environment To avoid unexpected charges, don't forget to delete your environment if you no longer need it. ❯ rosa delete cluster -c eric-rosa --watch\n? Are you sure you want to delete cluster eric-rosa? Yes\nI: Cluster 'eric-rosa' will start uninstalling now\nW: Logs for cluster 'eric-rosa' are not available\n…\n Conclusion To summarize, ROSA allows infrastructure and security teams to accelerate the deployment of the Red Hat OpenShift Service on AWS. Integration with NGINX Ingress Controller provides comprehensive L4-L7 security services for the application workloads running on Red Hat OpenShift Service on AWS (ROSA). As a developer, having your clusters as well as security services maintained by this service gives you the freedom to focus on deploying applications. You have two options for getting started with NGINX Ingress Controller: Download the NGINX Open Source-based version of NGINX Ingress Controller from our GitHub repo. If you prefer to bring your own license to AWS, get a free trial directly from F5 NGINX. ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"11614","kudosSumWeight":0,"repliesCount":0,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yOTEwMjMtNjI5N2k2NDJBNkY1RTc4MTlGRjAy?revision=1\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDI","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yOTEwMjMtMTQwNzZpQ0NENEQ3ODAwOEM2MjQzQw?revision=1\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDM","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yOTEwMjMtNjUzNGk1NzFBQUQ5M0VBREU3MDAz?revision=1\"}"}}],"totalCount":3,"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:297054":{"__typename":"Conversation","id":"conversation:297054","topic":{"__typename":"TkbTopicMessage","uid":297054},"lastPostingActivityTime":"2022-07-06T09:03:53.150-07:00","solved":false},"User:user:49440":{"__typename":"User","uid":49440,"login":"Chris_Zhang","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:49440"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yOTcwNTQtMTgzMzJpMDVGMTYyMkM1OTAyQ0FFQQ?revision=3\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yOTcwNTQtMTgzMzJpMDVGMTYyMkM1OTAyQ0FFQQ?revision=3","title":"compare-fibre-9HGPvHThNME-unsplash copy.jpg","associationType":"COVER","width":1000,"height":1000,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yOTcwNTQtMTgwOTVpQUEyNEU2RUYzMUY5MjNDMQ?revision=3\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yOTcwNTQtMTgwOTVpQUEyNEU2RUYzMUY5MjNDMQ?revision=3","title":"argoCD-cafe.png","associationType":"BODY","width":938,"height":612,"altText":null},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yOTcwNTQtMTgwOTZpNTE4ODEzRTQ4QUUwQkIwQw?revision=3\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0yOTcwNTQtMTgwOTZpNTE4ODEzRTQ4QUUwQkIwQw?revision=3","title":"argoCD-cafe-nap.png","associationType":"BODY","width":913,"height":304,"altText":null},"TkbTopicMessage:message:297054":{"__typename":"TkbTopicMessage","subject":"How to deploy NGINX App Protect WAF on the NGINX Ingress Controller using argoCD","conversation":{"__ref":"Conversation:conversation:297054"},"id":"message:297054","revisionNum":3,"uid":297054,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:49440"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":4428},"postTime":"2022-07-06T05:00:00.033-07:00","lastPublishTime":"2022-07-06T09:03:53.150-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" \n Overview \n The NGINX App Protect WAF can be deployed as an add-on within the NGINX Ingress Controller, making the two function in tandem as a WAF armed with a Kubernetes Ingress Controller. \n This repo leverages argoCD as a GitOps continuous delivery tool to showcase an end-to-end example of how to use the combo to frontend a simple Kubernetes application. \n As this repo is public facing, I am also using a tool named 'Sealed-Secrets' to encrypt all the secret manifests. However, this is not a requirement for deploying either component. \n I will go through argoCD and Sealed-Secrets first as supporting pieces and then go into NGINX App Protect WAF itself. \n Please note that this tutorial is applies to the NGINX Plus-based version of NGINX Ingress Controller. If you aren’t sure which version you’re using, read the blog A Guide to Choosing an Ingress Controller, Part 4: NGINX Ingress Controller Options. \n argoCD \n If you do not know argoCD, I strongly recommend that you check it out. In essence, with argoCD, you create an argoCD application that references a location (e.g., Git repo or folder) containing all your manifests. argoCD applies all the manifests in that location and constantly monitors and syncs changes from that location. e.g., if you made a change to a manifest or added a new one, after you did a Git commit for that change, argoCD picks it up and immediate applies the change within your Kubernetes. \n The following screenshot taken from argoCD shows that I have an app named 'cafe'. The 'cafe' app points to a Git repo where all manifests are stored. The status is 'Healthy' and 'Synced'. It means that argoCD has successfully applied all the manifests that it knows about, and these manifests are in sync with the Git repo. \n \n The cafe argoCD application manifest is shown here. For this repo, all argoCD application manifests are stored in the bootstrap folder. \n To add the Cafe argoCD application, run the following, \n kubectl apply -f cafe.yaml \n Sealed Secrets \n When Kubernetes manifests that contain secrets such as passwords and private keys, they cannot simply be pushed to a public repo. \n With Sealed-Secrets, you can solve this problem by sealing those manifests files offline via the binary and then push them to the public repo. When you apply the sealed secret manifests from the public repo, the sealed-secrets component that sits inside Kubernetes will decrypt the sealed secrets and then apply them on the fly. \n To do this, you must upload the encryption key into Kubernetes first. \n Please note that I am only using sealed secrets so I can push my secret manifests to a public repo, for the purpose of this demo. It is not a requirement to install NGINX App Protect WAF. If you have a private repo, you can simply push all your secret manifests there and argoCD will then apply them as is. \n The following commands set up sealed secrets with my specified certificate/key in its own namespace. \n export PRIVATEKEY=\"dc7.h.l.key\"\nexport PUBLICKEY=\"dc7.h.l.cer\"\nexport NAMESPACE=\"sealed-secrets\"\nexport SECRETNAME=\"dc7.h.l\"\n\nkubectl -n \"$NAMESPACE\" create secret tls \"$SECRETNAME\" --cert=\"$PUBLICKEY\" --key=\"$PRIVATEKEY\"\n\nkubectl -n \"$NAMESPACE\" label secret \"$SECRETNAME\" sealedsecrets.bitnami.com/sealed-secrets-key=active\nTo create a sealed TLS secret,\nkubectl create secret tls wildcard.abbagmbh.de --cert=wildcard.abbagmbh.de.cer --key=wildcard.abbagmbh.de.key -n nginx-ingress --dry-run=client -o yaml | kubeseal \\\n --controller-namespace sealed-secrets \\\n --format yaml \\\n > sealed-wildcard.abbagmbh.de.yaml\n \n NGINX App Protect WAF \n The NGINX App Protect WAF for Kubernetes is a NGINX Ingress Controller software security module add-on with L7 WAF capabilities. It can be embedded within the NGINX Ingress Controller. \n The installation process for NGINX App Protect WAF is identical to NGINX Ingress Controller, with the following additional steps. \n \n Apply NGINX App Protect WAF specific CRD's to Kubernetes \n Apply NGINX App Protect WAF log configuration (NGINX App Protect WAF logging is different from NGINX Plus) \n Apply NGINX App Protect WAF protection policy \n \n The official installation docs using manifests have great info around the entire process. This repo simply collated all the necessary manifests required for NGINX App Protect WAF in a directory that is then fed to argoCD. \n Image Pull Secret \n With the NGINX App Protect WAF docker image, you can either pull it from the official NGINX private repo, or from your own repo. In the former case, you would need to create a secret that is generated from the JWT file (part of the NGINX license files). See below for detail. \n To create a sealed docker-registry secret, \n username=`cat nginx-repo.jwt`\n\nkubectl create secret docker-registry private-registry.nginx.com \\\n--docker-server=private-registry.nginx.com \\\n--docker-username=$username \\\n--docker-password=none \\\n--namespace nginx-ingress \\\n--dry-run=client -o yaml | kubeseal \\\n --controller-namespace sealed-secrets \\\n --format yaml \\\n > sealed-docker-registry-secret.yaml\n \n Notice the controller namespace above, it needs to match the namespace where you installed Sealed-Secrets. \n NGINX App Protect WAF CRD's \n A number of NGINX App Protect WAF specific CRD's (Custom Resource Definition) are required for installation. They are included in the crds directory and should be picked up and applied by argoCD automatically. \n NGINX App Protect WAF Configuration \n The NGINX App Protect WAF configuration includes the followings in this demo: \n \n User defined signature \n NGINX App Protect WAF policy \n NGINX App Protect WAF log configuration \n \n This user defined signature shows an example of a custom signature that looks for keyword apple in request traffic. \n The NGINX App Protect WAF policy defines violation rules. In this case it blocks traffic caught by the custom signature defined above. This sample policy also enables data guard and all other protection features defined in a base template. \n The NGINX App Protect WAF log configuration defines what gets logged and how they look like. e.g., log all traffic versus log illegal traffic. \n This repo also includes a manifest for syslog deployment as a log destination used by NGINX App Protect WAF. \n Ingress \n To use NGINX App Protect WAF, you must create an Ingress resource. \n Within the Ingress manifest, you use annotations to apply NGINX App Protect WAF specific settings that were discussed above. \n apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n name: cafe-ingress\n annotations:\n kubernetes.io/ingress.class: \"nginx\"\n appprotect.f5.com/app-protect-policy: \"nginx-ingress/dataguard-alarm\"\n appprotect.f5.com/app-protect-enable: \"True\"\n appprotect.f5.com/app-protect-security-log-enable: \"True\"\n appprotect.f5.com/app-protect-security-log: \"nginx-ingress/logconf\"\n appprotect.f5.com/app-protect-security-log-destination: \"syslog:server=syslog-svc.nginx-ingress:514\"\nThe traffic routing logic is done via the followings,\nspec:\n ingressClassName: nginx # use only with k8s version >= 1.18.0\n tls:\n - hosts:\n - cafe.abbagmbh.de\n secretName: wildcard.abbagmbh.de\n rules:\n - host: cafe.abbagmbh.de\n http:\n paths:\n - path: /tea\n pathType: Prefix\n backend:\n service:\n name: tea-svc\n port:\n number: 8080\n - path: /coffee\n pathType: Prefix\n backend:\n service:\n name: coffee-svc\n port:\n number: 8080\n \n Testing \n Once you added both applications (in bootstrap folder) into argoCD, you should see the followings in argoCD UI. \n \n We can do a test to confirm if NGINX App Protect WAF routes traffic based upon HTTP URI, as well as whether WAF protection is applied. \n First get the NGINX Ingress Controller IP. \n % kubectl get ingress\nNAME CLASS HOSTS ADDRESS PORTS AGE\ncafe-ingress nginx cafe.abbagmbh.de x.x.x.x 80, 443 1d\n \n Now send traffic to both '/tea' and '/coffee' URI paths. \n % curl --resolve cafe.abbagmbh.de:443:x.x.x.x https://cafe.abbagmbh.de/tea\nServer address: 10.244.0.22:8080\nServer name: tea-6fb46d899f-spvld\nDate: 03/May/2022:06:02:24 +0000\nURI: /tea\nRequest ID: 093ed857d28e160b7417bb4746bec774\n\n% curl --resolve cafe.abbagmbh.de:443:x.x.x.x https://cafe.abbagmbh.de/coffee\nServer address: 10.244.0.21:8080\nServer name: coffee-6f4b79b975-7fwwk\nDate: 03/May/2022:06:03:51 +0000\nURI: /coffee\nRequest ID: 0744417d1e2d59329401ed2189067e40\n \n As you can see from above, traffic destined to '/tea' is routed to the tea pod (tea-6fb46d899f-spvld) and traffic destined to '/coffee' is routed to the coffee pod (coffee-6f4b79b975-7fwwk). \n Let us trigger a violation based on the user defined signature, \n % curl --resolve cafe.abbagmbh.de:443:x.x.x.x https://cafe.abbagmbh.de/apple\n\n<html><head><title>Request Rejected</title></head><body>The requested URL was rejected. Please consult with your administrator.<br><br>Your support ID is: 10807744421744880061<br><br><a href='javascript:history.back();'>[Go Back]</a></body></html>\n Finally, traffic violating the XSS rule. curl --resolve cafe.abbagmbh.de:443:x.x.x.x 'https://cafe.abbagmbh.de/tea<script>'\n\n<html><head><title>Request Rejected</title></head><body>The requested URL was rejected. Please consult with your administrator.<br><br>Your support ID is: 10807744421744881081<br><br><a href='javascript:history.back();'>[Go Back]</a></body></html>\n \n Confirming that logs are received on the syslog pod. \n % tail -f /var/log/message\n\nMay 3 06:30:32 nginx-ingress-6444787b8-l6fzr ASM:attack_type=\"Non-browser Client Abuse of Functionality Cross Site Scripting (XSS)\"\nblocking_exception_reason=\"N/A\"\ndate_time=\"2022-05-03 06:30:32\"\ndest_port=\"443\"\nip_client=\"x.x.x.x\"\nis_truncated=\"false\"\nmethod=\"GET\"\npolicy_name=\"dataguard-alarm\"\nprotocol=\"HTTPS\"\nrequest_status=\"blocked\"\nresponse_code=\"0\"\nseverity=\"Critical\"\nsig_cves=\" \"\nsig_ids=\"200000099 200000093\"\nsig_names=\"XSS script tag (URI) XSS script tag end (URI)\"\nsig_set_names=\"{Cross Site Scripting Signatures;High Accuracy Signatures} {Cross Site Scripting Signatures;High Accuracy Signatures}\"\nsrc_port=\"1478\"\nsub_violations=\"N/A\"\nsupport_id=\"10807744421744881591\"\nthreat_campaign_names=\"N/A\"\nunit_hostname=\"nginx-ingress-6444787b8-l6fzr\"\nuri=\"/tea<script>\"\nviolation_rating=\"5\"\nvs_name=\"24-cafe.abbagmbh.de:8-/tea\"\nx_forwarded_for_header_value=\"N/A\"\noutcome=\"REJECTED\"\noutcome_reason=\"SECURITY_WAF_VIOLATION\"\nviolations=\"Illegal meta character in URL\nAttack signature detected\nViolation Rating Threat detected\nBot Client Detected\"\njson_log=\"{violations:[{enforcementState:{isBlocked:false}\nviolation:{name:VIOL_URL_METACHAR}}\n{enforcementState:{isBlocked:true}\nviolation:{name:VIOL_RATING_THREAT}}\n{enforcementState:{isBlocked:true}\nviolation:{name:VIOL_BOT_CLIENT}}\n{enforcementState:{isBlocked:true}\nsignature:{name:XSS script tag (URI)\nsignatureId:200000099}\nviolation:{name:VIOL_ATTACK_SIGNATURE}}\n{enforcementState:{isBlocked:true}\nsignature:{name:XSS script tag end (URI)\nsignatureId:200000093}\nviolation:{name:VIOL_ATTACK_SIGNATURE}}]}\"\n \n Conclusion \n The NGINX App Protect WAF deploys as a software security module add-on to the NGINX Ingress Controller and provides comprehensive application security for your Kubernetes environment. \n I hope that you find the deployment simple and straightforward. \n ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"11790","kudosSumWeight":5,"repliesCount":0,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yOTcwNTQtMTgzMzJpMDVGMTYyMkM1OTAyQ0FFQQ?revision=3\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDI","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yOTcwNTQtMTgwOTVpQUEyNEU2RUYzMUY5MjNDMQ?revision=3\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDM","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0yOTcwNTQtMTgwOTZpNTE4ODEzRTQ4QUUwQkIwQw?revision=3\"}"}}],"totalCount":3,"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:307816":{"__typename":"Conversation","id":"conversation:307816","topic":{"__typename":"TkbTopicMessage","uid":307816},"lastPostingActivityTime":"2023-06-05T21:36:33.595-07:00","solved":false},"User:user:195330":{"__typename":"User","uid":195330,"login":"momahdy","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/images/dS0xOTUzMzAtaENpUGx2?image-coordinates=0%2C588%2C1080%2C1668"},"id":"user:195330"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDc4MTYtMjE1NzNpQUQ2OUQ4QjMxRUVDRjEyMA?revision=6\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDc4MTYtMjE1NzNpQUQ2OUQ4QjMxRUVDRjEyMA?revision=6","title":"mmahdy_0-1673373623199.png","associationType":"BODY","width":1560,"height":1296,"altText":null},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDc4MTYtMjE1NzRpREVGMjUwOTI4RjE0MURDOQ?revision=6\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDc4MTYtMjE1NzRpREVGMjUwOTI4RjE0MURDOQ?revision=6","title":"mmahdy_1-1673374155478.png","associationType":"BODY","width":1495,"height":1339,"altText":null},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDc4MTYtMjE1NzVpMUFGQTVERUUwMEFCOEY2MA?revision=6\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDc4MTYtMjE1NzVpMUFGQTVERUUwMEFCOEY2MA?revision=6","title":"mmahdy_2-1673374359242.png","associationType":"BODY","width":1647,"height":1211,"altText":null},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDc4MTYtMjE1NzZpRjk5MzNDMTY5N0Q5MzlGMg?revision=6\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDc4MTYtMjE1NzZpRjk5MzNDMTY5N0Q5MzlGMg?revision=6","title":"mmahdy_3-1673375922537.png","associationType":"BODY","width":1764,"height":1150,"altText":null},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDc4MTYtMjE1NzdpRTQwNDk3M0YyRjgwRkMyRA?revision=6\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDc4MTYtMjE1NzdpRTQwNDk3M0YyRjgwRkMyRA?revision=6","title":"mmahdy_4-1673377558747.png","associationType":"BODY","width":2016,"height":1016,"altText":null},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDc4MTYtMjE1ODJpRjEzNUZEMjZGNkNGRDk0Qw?revision=6\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDc4MTYtMjE1ODJpRjEzNUZEMjZGNkNGRDk0Qw?revision=6","title":"mmahdy_0-1673428693513.png","associationType":"BODY","width":1894,"height":1418,"altText":null},"TkbTopicMessage:message:307816":{"__typename":"TkbTopicMessage","subject":"Application Programming Interface (API) Authentication types simplified","conversation":{"__ref":"Conversation:conversation:307816"},"id":"message:307816","revisionNum":6,"uid":307816,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:195330"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":" API is a critical part of most of our modern applications. In this article we will walkthrough the different authentication types, to help us in the future articles covering NGINX API Connectivity Manager authentication and NGINX Single Sign-on. ","introduction":"","metrics":{"__typename":"MessageMetrics","views":4066},"postTime":"2023-01-24T08:00:00.015-08:00","lastPublishTime":"2023-06-05T21:36:33.595-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" Introduction API Authentication and Authorization Basic Authentication API Key Authentication Bearer Authentication Open Authorization (OAuth 2.0) OAuth Token Introspection OpenID Connect (OIDC) References \n \n Introduction \n API is a critical part of most of our modern applications. In this article we will walkthrough the different authentication types, to help us in the future articles covering NGINX Management Suite API Connectivity Manager authentication and NGINX Single Sign-on. \n This separate article will cover the different authentication types and how they work with clients and servers. \n API Authentication and Authorization \n It may sound a bit basic, but getting back to the basic concepts help us understand, innovate and develop more secure designs. \n Authentication, is the act of validating that users are whom they claim to be. \n Authorization, is the process of giving a user the permission access/ perform specific function. \n Below, we will explore the different API authentication types, \n \n Basic Authentication. \n API Key Authentication. \n Bearer Authentication. \n Open Authorization (OAuth 2.0). \n OAuth Token Introspection. \n OpenID Connect (OIDC). \n \n Basic Authentication \n HTTP Basic authentication, is a method for user agent (e.x Browser) to provide credentials to a web server. The request contains a specific header to provide base64 encoded credentials. \n Credentials are already shared with the clients before clients can access the server using this method. \n Example, Authorization: Basic <credentials> \n \n API Key Authentication \n An API key is a token that a client provides when making API calls. not to conflict this method with secure tokens generated via OAuth, in this type, the API keys are generated whether at the application or API key server, then those keys are distributed to the clients to be used for accessing the application. \n API Key can be inserted in different location in the HTTP request, \n \n As a Query parameter in the HTTP request URL. \n As a Request header. \n As a Cookie. \n \n \n Bearer Authentication \n Bearer Authentication can be considered an early step to token authentication mechanisms, it depends on initial users credentials to validate them and issue a time limited token for a specific service. \n \n User provides credentials over POST request to the server. \n The server validates the credentials and provides a token with expiry date/time to the user. \n The server then validate future requests to check the token validity and provide response based on that. \n \n \n Open Authorization (OAuth 2.0) \n At first sight, the question might be why we are referencing authorization yet we are discussing authentication. \n Let's check the basic definition, OAuth is an open standard for access delegation, commonly used for internet users (untrusted medium) to grant websites (resource server) access to user information at other websites (OAuth authorization server) without providing their passwords. \n Performing Authentication via OAuth can be referred to as (Pseudo-authentication),and it's very similar to OIDC Authentication approach which will be discussed in the following section. \n \n User request a resource or a site login. \n The site sees that the user is not authenticated, It formulates a request for the identity provider, encodes it, and redirect the user to the identity provider. \n The user's browser makes a request to the redirect URL for the identity provider, including the application's request \n Once the identity provider is satisfied that the user is sufficiently authenticated, it processes the application's request, formulates a response, and redirect the user browser back to the application. \n The user's browser requests the redirect URL that goes back to the application, including the identity provider's response. \n The application decodes the identity provider's response, and carries on accordingly. \n (For OAuth) The response includes an access token which the application can use to gain direct access to the identity provider's services on the user's behalf. \n \n\n \n OAuth Token Introspection \n In the previous section, we explored the idea of OAuth token authentication, and using API gateway whenever it recieves a request it starts the redirection process to the Identity provider and receive the SAML insertion response back that verifies the user and then the user is allowed to access a protected resource. \n In Token introspection, API gateway receives the token from the OAuth client and communicate with the Authorization server to query meta information regarding the presented token for example (If the token still active, the access privilege and the authorization context). \n\n \n OpenID Connect (OIDC) \n OpenID is an open standard for decentralized authentication, It allows authentication by (Relying sites) using third-party providers (Identity Providers) to eliminate the need for application owners to create their own login systems and allow the users to use different applications without passing their credentials over internet to different entities. \n OIDC is built on top of OAuth2.0 framework, that explains the common parts we can see between both frameworks. \n \n\n The main difference observed between OAuth vs OIDC can be explained in the following example, \n \n OIDC Auth:\n \n The user request access to an application. \n The application reply with a question, who is this user ? \n The user is redirected to an identity provider to certify that this is a valid user and issue relevant token. \n The user redirected back to the application with the obtained token. \n \n \n OAuth authentication\n \n The user request access to an application. \n The application reply with a question, Do you have access key ? \n The user is redirected to an identity provider to get a key to obtain access to the application. \n The user redirected back to the application with the obtained key. \n \n \n \n In this article, we went through the common API Authentication types, the following articles will cover use cases for API authentication whether directly through NGINX Plus or API Connectivity Manager. \n\n References \n OAuth protocol \n OAuth Token introspection \n OpenID Connect \n NGINX Plus \n NGINX Management Suite API Connectivity Manager \n ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"6358","kudosSumWeight":5,"repliesCount":0,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDc4MTYtMjE1NzNpQUQ2OUQ4QjMxRUVDRjEyMA?revision=6\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDI","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDc4MTYtMjE1NzRpREVGMjUwOTI4RjE0MURDOQ?revision=6\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDM","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDc4MTYtMjE1NzVpMUFGQTVERUUwMEFCOEY2MA?revision=6\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDQ","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDc4MTYtMjE1NzZpRjk5MzNDMTY5N0Q5MzlGMg?revision=6\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDU","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDc4MTYtMjE1NzdpRTQwNDk3M0YyRjgwRkMyRA?revision=6\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDY","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDc4MTYtMjE1ODJpRjEzNUZEMjZGNkNGRDk0Qw?revision=6\"}"}}],"totalCount":6,"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:304550":{"__typename":"Conversation","id":"conversation:304550","topic":{"__typename":"TkbTopicMessage","uid":304550},"lastPostingActivityTime":"2022-12-21T05:00:00.015-08:00","solved":false},"User:user:172159":{"__typename":"User","uid":172159,"login":"Leon_Seng","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/images/dS0xNzIxNTktMjA5NDNpQTcyQThGQzE5NUQ0MzZFMg"},"id":"user:172159"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDQ1NTAtMjA4MjFpOTUyODU2OTRDMTFBNDM3RA?revision=11\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDQ1NTAtMjA4MjFpOTUyODU2OTRDMTFBNDM3RA?revision=11","title":"Leon_Seng_4-1669175623516.png","associationType":"BODY","width":910,"height":637,"altText":null},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDQ1NTAtMjA5NjVpQzk1MjkxQTdFNkRCRDM0Mg?revision=11\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDQ1NTAtMjA5NjVpQzk1MjkxQTdFNkRCRDM0Mg?revision=11","title":"Leon_Seng_0-1670365185000.png","associationType":"BODY","width":971,"height":136,"altText":null},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDQ1NTAtMjA4NTNpRjI2QUNDRjA3ODc2OTc2QQ?revision=11\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDQ1NTAtMjA4NTNpRjI2QUNDRjA3ODc2OTc2QQ?revision=11","title":"kibana.png","associationType":"BODY","width":1489,"height":245,"altText":null},"TkbTopicMessage:message:304550":{"__typename":"TkbTopicMessage","subject":"Managing NGINX App Protect WAF for Beginners","conversation":{"__ref":"Conversation:conversation:304550"},"id":"message:304550","revisionNum":11,"uid":304550,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:172159"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":3805},"postTime":"2022-12-21T05:00:00.015-08:00","lastPublishTime":"2022-12-21T05:00:00.015-08:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" \n F5 NGINX App Protect WAF brings much of the tried-and-true capabilities of the F5 BIG-IP Advanced WAF to the DevOps environment, which demand performance without compromising on delivery velocity. However, as security capabilities like a WAF are traditionally handled by dedicated security teams, DevOps and application teams may find themselves out of their comfort zone when it comes to securing their applications. Having deployed NGINX App Protect WAF with <insert your favourite CI/CD tooling> in your environment, you may find yourself asking \"what next?\" \n \n \n Figure 1: NGINX App Protect WAF and DoS security solution deployment options \n NGINX App Protect is a modern app security solution that works seamlessly in DevOps environments and is available as a robust WAF or as a DoS product for app layer defense. Each can be deployed on NGINX Plus in the image shown above. For the purpose of this article, we will be focusing on the WAF product. In this post, I will provide some basic steps to help you get started with operating your NGINX App Protect WAF. \n Some mitigation is better than none \n Application security is a complex field, just take a look at the security features supported by NGINX App Protect WAF. It is easy to be overwhelmed by the sheer amount of security jargons, let alone identifying the features relevant for your application, leading to a case of analysis paralysis. \n Simplifying a lot of this jargon into intent-based policies is a big focus at F5. Instead of talking about signatures that detect malicious traffic based on certain patterns, it could be as simple as saying \n \n \"I don't want untrusted or malicious bots accessing my application\", or \n \"Sign me up for F5 Threat Campaigns to deal with what's in the wild now\" \n \n Some form of mitigation is better than none, so start with simple policies, shown here, to deal with a large amount of unwanted traffic from the Internet. With time, the WAF policy can be tuned based on learnings from the information provided by NGINX App Protect WAF. \n If there are concerns about the WAF unintentionally blocking legitimate traffic and creating a negative experience for your users, configure the policy to be in transparent mode instead of blocking. \n Making sense of the information \n With a good amount of security coverage now enabled for your application, let us shift our focus to the information that NGINX App Protect WAF provides to you. \n NGINX App Protect WAF conveys security events in the form of logs rich with information, which can be exported via syslog to external logging and monitoring platforms such as an ELK stack, Splunk, or Grafana. These platforms provide powerful search capabilities which enables easier consumption of security events, simplifying some of the day 2 activities - a couple of which are covered in the next section. If anything, they show how much unwanted traffic are trying to access your applications, but are blocked by NGINX App Protect WAF! \n For those interested in having high level information immediately, you can also use the information to build dashboards such as the ones here: \n \n https://github.com/f5devcentral/f5-waf-elk-dashboards \n https://github.com/skenderidis/nap-dashboard \n \n Day 2 and onwards \n With NGINX App Protect WAF up and running, much of the operational activities will involve keeping the NGINX App Protect WAF attack signatures updated, which can be easily automated. \n Tuning the WAF policy is also a major part of managing NGINX App Protect WAF. A common trigger for WAF tuning is the discovery of a new exploit affecting your applications. In such cases, look up \"NGINX App Protect\" and the name of the exploit online, and you should find mitigation steps provided by F5. One example is this article on how to Mitigate the Apache Log4j2 vulnerability with NGINX Application Security products. \n Another trigger would be when you start seeing support tickets from your users containing messages as below, indicating that they have been blocked by NGINX App Protect WAF. \n \n Image 1: A support ticket message from NGINX App Protect WAF that provides a Support ID which can be used to obtain further insights. \n For this, look up the support ID in the NGINX App Protect WAF security logs (this is where the use of ELK, Splunk and Grafana come in handy), and review the corresponding log entry which contains information on the user request and the reason the request was blocked. \n \n \n Image 2: A screenshot of log entries displayed from a Kibana dashboard. \n If a request is deemed incorrectly blocked by NGINX App Protect WAF, it is known as a false positive, which can often happen when a WAF is first deployed, or changes are recently made to the application, introducing new behaviours previously not considered when defining the WAF policy. The WAF policy can then be updated to disregard the corresponding signatures or violations, allowing your users to access your application once again. \n As you get more comfortable with NGINX App Protect WAF, there are other areas of improvement that can be explored, such as implementing WAF policy as code for easier CI/CD pipeline integration, or analyzing the information provided by NGINX App Protect WAF to understand the attack surfaces on your applications, enabling you to focus your security efforts where it counts. \n Closing \n Hopefully, the information above gives you a better perspective of what is involved in managing NGINX App Protect WAF. In closing, the goal of NGINX App Protect WAF is to secure your application with minimal effort, and have you focus your efforts on delivering business value through your application instead. \n ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"5765","kudosSumWeight":3,"repliesCount":0,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDQ1NTAtMjA4MjFpOTUyODU2OTRDMTFBNDM3RA?revision=11\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDI","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDQ1NTAtMjA5NjVpQzk1MjkxQTdFNkRCRDM0Mg?revision=11\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDM","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDQ1NTAtMjA4NTNpRjI2QUNDRjA3ODc2OTc2QQ?revision=11\"}"}}],"totalCount":3,"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:303007":{"__typename":"Conversation","id":"conversation:303007","topic":{"__typename":"TkbTopicMessage","uid":303007},"lastPostingActivityTime":"2024-03-19T16:03:38.001-07:00","solved":false},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDMwMDctMjE2NzFpNERFNjhDRERGMDI5NkQ2Mg?revision=58\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDMwMDctMjE2NzFpNERFNjhDRERGMDI5NkQ2Mg?revision=58","title":"nginx-multiple-region.png","associationType":"BODY","width":1280,"height":860,"altText":"Figure 1 Full Demo"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDMwMDctMjE2NTdpMTRERDE4MkQ2QjdBMTVFNQ?revision=58\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDMwMDctMjE2NTdpMTRERDE4MkQ2QjdBMTVFNQ?revision=58","title":"n4a-architecture.png","associationType":"BODY","width":2048,"height":1006,"altText":"Figure 2 High Level"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDMwMDctMjE2NzJpRTA3QUEyQzM3MUYwREQ0NQ?revision=58\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDMwMDctMjE2NzJpRTA3QUEyQzM3MUYwREQ0NQ?revision=58","title":"nginx-gslb-example.png","associationType":"BODY","width":840,"height":784,"altText":"Figure 3 GSLB"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDMwMDctMjAyNjhpRjM3ODA1N0UzN0FFMDFDMA?revision=58\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDMwMDctMjAyNjhpRjM3ODA1N0UzN0FFMDFDMA?revision=58","title":"nginx-customer-subscription1.png","associationType":"BODY","width":799,"height":698,"altText":"Figure 4 Hub and Spoke"},"TkbTopicMessage:message:303007":{"__typename":"TkbTopicMessage","subject":"F5 NGINXaaS for Azure: Multi-Region Architecture","conversation":{"__ref":"Conversation:conversation:303007"},"id":"message:303007","revisionNum":58,"uid":303007,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:49688"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":3373},"postTime":"2022-11-15T10:03:26.521-08:00","lastPublishTime":"2024-03-19T16:03:38.001-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" \n The F5 NGINXaaS for Azure offering recently announced general availability. Trust me...I've been using it and having fun! In this article, I will show you an example hub and spoke architecture using GitHub Actions and Azure Functions to automate NGINX configurations. As a bonus, I have code on GitHub that you can use to deploy this example. \n Topics Covered: \n \n NGINXaaS for Azure Architecture Explained \n The NGINXaaS for Azure architecture consists of an F5 subscription as well as customer subscription. \n \n F5 subscription - hidden from user, NGINX Plus instances, control plane, data plane \n Customer subscription - eNICs from VNet Injection, customer network stack, customer workloads \n \n F5 Subscription \n The NGINXaaS offering creates NGINX Plus instances and other related components like NGINX control plane and data plane resources in the F5 subscriptions. These items are not visible to the end user, and therefore result in the operational tasks of upgrades and scaling being managed by the NGINXaaS offering instead of the user. \n Each NGINX deployment, like other Azure services, is regional in nature. If you need to deploy NGINX closer to the client, then this will require multiple NGINX deployments (ex. westus2, eastus2). Each NGINX deployment will have a unique listener address. You can then use DNS to send clients to an NGINX deployment in the nearest region. Here is an example diagram. \n Customer Subscription \n The customer subscription has items like network stacks, Key Vaults, monitoring, application workloads, and more. The NGINX deployment automatically creates ethernet NICs (eNICs) in the customer subscription using VNet Injection and subnet delegation. The eNICs are deployed inside their own Azure Resource Group. They receive IP addressing from the customer VNet and are indeed visible by the user. However, there is no management needed with the eNICs because they are part of the NGINX deployment. \n Note: In my testing during public preview, I have noticed that Azure lets you manually remove subnet delegation for the NGINX service. Warning...do NOT do this. It will break traffic flow. \n Hub and Spoke Architecture \n You can easily make a hub and spoke design with NGINX in the mix using VNet peering. This is a great use case when required to use a shared NGINX deployment across different VNets, environments, or scaling workloads across multiple regions. Recall from earlier that an NGINX deployment will automatically create eNICs in the customer subscription. Therefore, you can control the entry point into the customer environment and the traffic flows. \n For example, configuring NGINX to use a customer shared VNet with peering gives you a hub and spoke design such as the picture below. This results in the NGINX eNICs being deployed into a customer Shared VNet (hub). Meanwhile the customer places workloads into their own VNets (spokes). \n Demo Code \n If this is the first time deploying NGINXaaS for Azure in your subscription, then you will need to subscribe to it in the marketplace. \n \n Search for “F5 NGINXaaS for Azure” in marketplace or follow this link \n Select F5 NGINXaaS for Azure and choose \"Public Preview\" and subscribe \n \n Time to play with code! Click the link below and review the README to deploy the demo example. There are prerequisites to follow. For example, you need to have a GitHub repository that stores the NGINX configuration files. You also need to have an Azure Key Vault and secret containing your GitHub access token. These are explained in the README. \n GitHub repo - F5 NGINXaaS for Azure Deployment with Demo Application in Multiple Regions \n After the deployment is done, you have a few options on how to handle NGINX configurations. I will share examples in future articles, but for now go ahead and explore on your own. Refer to the NGINXaaS for Azure documentation \"NGINX Configuration\" to get started. \n \n \n Summary \n This article gives an example architecture for deploying the NGINXaaS for Azure offering. I shared details on the different NGINX components, and I also shared demo code to help you explore the solution on your own! \n Contact us with any questions or requirements. We would love to hear from you! \n Resources \n \n DevCentral Series - F5 NGINXaaS for Azure \n F5 NGINXaaS for Azure Docs \n Blog Introducing F5 NGINXaaS for Azure \n \n ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"4387","kudosSumWeight":6,"repliesCount":2,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDMwMDctMjE2NzFpNERFNjhDRERGMDI5NkQ2Mg?revision=58\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDI","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDMwMDctMjE2NTdpMTRERDE4MkQ2QjdBMTVFNQ?revision=58\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDM","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDMwMDctMjE2NzJpRTA3QUEyQzM3MUYwREQ0NQ?revision=58\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDQ","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMDMwMDctMjAyNjhpRjM3ODA1N0UzN0FFMDFDMA?revision=58\"}"}}],"totalCount":4,"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:323254":{"__typename":"Conversation","id":"conversation:323254","topic":{"__typename":"TkbTopicMessage","uid":323254},"lastPostingActivityTime":"2025-05-06T11:26:29.626-07:00","solved":false},"User:user:194786":{"__typename":"User","uid":194786,"login":"Janibasha","registrationData":{"__typename":"RegistrationData","status":null},"deleted":false,"avatar":{"__typename":"UserAvatar","url":"https://community.f5.com/t5/s/zihoc95639/images/dS0xOTQ3ODYtMjA5NDJpMEI1Q0JDRDNGRkQ2MUM0Mw"},"id":"user:194786"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtMjM4OTZpQTE0Q0ZFMTVFMTBCOEFFMw?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtMjM4OTZpQTE0Q0ZFMTVFMTBCOEFFMw?revision=54","title":"DC-Cover_0001_mateusz-klein-ADvHWx2wV5Y-unsplash.jpg","associationType":"COVER","width":500,"height":500,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtM2hGd1pF?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtM2hGd1pF?revision=54","title":"Screenshot 2025-04-24 at 6.32.12 PM.png","associationType":"BODY","width":2934,"height":1380,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtSFA1OHpa?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtSFA1OHpa?revision=54","title":"Screenshot 2025-04-24 at 12.02.26 PM.png","associationType":"BODY","width":2254,"height":1818,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtam1vTFIx?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtam1vTFIx?revision=54","title":"Screenshot 2025-04-24 at 2.31.47 PM.png","associationType":"BODY","width":2814,"height":322,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtaU9YQ1dG?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtaU9YQ1dG?revision=54","title":"Screenshot 2025-04-24 at 2.00.08 PM.png","associationType":"BODY","width":1194,"height":2062,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtUTNveEdt?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtUTNveEdt?revision=54","title":"Screenshot 2025-04-24 at 2.35.48 PM.png","associationType":"BODY","width":2622,"height":324,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtMTJXT2VX?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtMTJXT2VX?revision=54","title":"Screenshot 2025-04-24 at 2.37.44 PM.png","associationType":"BODY","width":3442,"height":884,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtQVNLUFpr?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtQVNLUFpr?revision=54","title":"Screenshot 2025-04-24 at 3.17.37 PM.png","associationType":"BODY","width":2626,"height":1682,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtNkptMjNQ?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtNkptMjNQ?revision=54","title":"Screenshot 2025-04-24 at 3.27.56 PM.png","associationType":"BODY","width":1708,"height":1144,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtbDFGUXlO?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtbDFGUXlO?revision=54","title":"Screenshot 2025-04-24 at 3.26.33 PM.png","associationType":"BODY","width":2598,"height":1556,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtVkVCdGNq?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtVkVCdGNq?revision=54","title":"Screenshot 2025-04-24 at 3.22.37 PM.png","associationType":"BODY","width":2602,"height":1546,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtOWFxQmRp?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtOWFxQmRp?revision=54","title":"Screenshot 2025-04-24 at 3.22.54 PM copy.png","associationType":"BODY","width":3442,"height":702,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtMjYxMjlpM0Y0QkY4NTRBM0JBRkYyRA?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtMjYxMjlpM0Y0QkY4NTRBM0JBRkYyRA?revision=54","title":"rate-limit.jpg","associationType":"BODY","width":3789,"height":2297,"altText":"rate-limit.jpg"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtMjYxMzBpMEYwNzM4ODY5M0VGMEVBQg?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtMjYxMzBpMEYwNzM4ODY5M0VGMEVBQg?revision=54","title":"rate-block.JPG","associationType":"BODY","width":2962,"height":1633,"altText":"rate-block.JPG"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtMjYxMzhpRTc5QTFGODZENDA1MDgwRg?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtMjYxMzhpRTc5QTFGODZENDA1MDgwRg?revision=54","title":"rate-limiting-web.jpg","associationType":"BODY","width":3840,"height":2400,"altText":"rate-limiting-web.jpg"},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtdHJDRDBk?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtdHJDRDBk?revision=54","title":"Screenshot 2025-04-29 at 10.02.14 AM.png","associationType":"BODY","width":2596,"height":1282,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtblBiMVRI?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtblBiMVRI?revision=54","title":"Screenshot 2025-04-29 at 12.28.46 PM.png","associationType":"BODY","width":2586,"height":1386,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtcXAzcUFn?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtcXAzcUFn?revision=54","title":"Screenshot 2025-04-29 at 10.02.58 AM.png","associationType":"BODY","width":2070,"height":1698,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtbVU4MEg3?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtbVU4MEg3?revision=54","title":"Screenshot 2025-04-29 at 10.34.10 AM.png","associationType":"BODY","width":1986,"height":2172,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtWGZkOURX?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtWGZkOURX?revision=54","title":"Screenshot 2025-04-29 at 10.30.50 AM.png","associationType":"BODY","width":2586,"height":1368,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtRFluak1Z?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtRFluak1Z?revision=54","title":"Screenshot 2025-04-29 at 10.31.53 AM.png","associationType":"BODY","width":3456,"height":732,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtYnc0aEdj?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtYnc0aEdj?revision=54","title":"NAP-API-SC-1.png","associationType":"BODY","width":1960,"height":848,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtQ0ZueUlP?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtQ0ZueUlP?revision=54","title":"NAP-API-SC-2.png","associationType":"BODY","width":1958,"height":780,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtYVhQNTVD?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtYVhQNTVD?revision=54","title":"nap_api_8_policy.png","associationType":"BODY","width":1100,"height":998,"altText":""},"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtY3kyMzAx?revision=54\"}":{"__typename":"AssociatedImage","url":"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtY3kyMzAx?revision=54","title":"NAP-API-SC-3.png","associationType":"BODY","width":1962,"height":800,"altText":""},"TkbTopicMessage:message:323254":{"__typename":"TkbTopicMessage","subject":"Mitigating OWASP 2019 API Security Top 10 risks using F5 NGINX App Protect","conversation":{"__ref":"Conversation:conversation:323254"},"id":"message:323254","revisionNum":54,"uid":323254,"depth":0,"board":{"__ref":"Tkb:board:TechnicalArticles"},"author":{"__ref":"User:user:194786"},"teaser@stripHtml({\"removeProcessingText\":true,\"truncateLength\":-1})":"","introduction":"","metrics":{"__typename":"MessageMetrics","views":2750},"postTime":"2023-11-13T05:00:00.021-08:00","lastPublishTime":"2025-05-06T11:26:29.626-07:00","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})":" \n This 2019 API Security article provides a valuable summary of the OWASP API Security Top 10 risks identified for that year, outlining key vulnerabilities. \n We will deep-dive into some of those common risks and how we can protect our applications against these vulnerabilities using F5 NGINX App Protect. \n API2:2019 - Broken User Authentication \n Problem Statement: \n A critical API security risk, Broken Authentication occurs when weaknesses in the API's identity verification process permit attackers to circumvent authentication mechanisms. Successful exploitation leads attackers to impersonate legitimate users, gain unauthorized access to sensitive data, perform actions on behalf of victims, and potentially take over accounts or systems. \n This demonstration utilizes the Damn Vulnerable Web Application (DVWA) to illustrate the exploitability of Broken Authentication. We will execute a brute-force attack against the login interface, iterating through potential credential pairs to achieve unauthorized authentication. \n \n Below is the selenium automated script to execute brute-force attack, submitting multiple credential combinations to attempt authentication. \n \n The brute-force attack successfully compromised the authentication controls by iterating through multiple credential pairs, ultimately granting access. \n \n Solution: \n To mitigate the above vulnerability, NGINX App Protect is deployed and configured as reverse proxy in front of the application and requests are first validated by NAP for the vulnerabilities. The NGINX App Protect Brute Force WAF policy is utilized as shown below. \n \n Re-attempt to gain access to the application using the brute force approach is rejected and blocked. \n \n Support ID verification in the Security logs shows request is blocked because of Brute Force Policy. \n Request captured in NGINX App Protect security log\n API3:2019 - Excessive Data Exposure \n Problem Statement: \n As shown below in one of the demo application API’s, Personal Identifiable Information (PII) data, like Credit Card Numbers (CCN) and U.S. Social Security Numbers (SSN), are visible in responses that are highly sensitive. So, we must hide these details to prevent personal data exploits. \n \n Solution: \n To prevent this vulnerability, we will use the DataGuard feature in NGINX App Protect, which validates all response data for sensitive details and will either mask the data or block those requests, as per the configured settings. First, we will configure DataGuard to mask the PII data as shown below and will apply this configuration. \n \n Next, if we resend the same request, we can see that the CCN/SSN numbers are masked, thereby preventing data breaches. \n \n If needed, we can update configurations to block this vulnerability after which all incoming requests for this endpoint will be blocked. \n \n If you open the security log and filter with this support ID, we can see that the request is either blocked or PII data is masked, as per the DataGuard configuration applied in the above section. \n Request captured in NGINX App Protect security log\n API4:2019 - Lack of Resources & Rate Limiting \n Problem Statement: \n APIs do not have any restrictions on the size or number of resources that can be requested by the end user. Above mentioned scenarios sometimes lead to poor API server performance, Denial of Service (DoS), and brute force attacks. \n Solution: \n NGINX App Protect provides different ways to rate limit the requests as per user requirements. A simple rate limiting use case configuration is able to block requests after reaching the limit, which is demonstrated below. \n \n \n API6:2019 - Mass Assignment \n Problem Statement: \n API Mass Assignment vulnerability arises when clients can modify immutable internal object properties via crafted requests, bypassing API Endpoint restrictions. Attackers exploit this by sending malicious HTTP requests to escalate privileges, bypass security mechanisms, or manipulate the API Endpoint's functionality. \n Placing an order with quantity as 1: \n \n Bypassing API Endpoint restrictions and placing the order with quantity as -1 is also successful. \n \n Solution: \n To overcome this vulnerability, we will use the WAF API Security Policy in NGINX App Protect which validates all the API Security event triggered and based on the enforcement mode set in the validation rules, the request will either get reported or blocked, as shown below. \n Restricted/updated swagger file with .json extension is added as below: \n \n Policy used: App Protect API Security \n \n Re-attempting to place the order with quantity as -1 is getting blocked. \n \n Validating the support ID in Security log as below: \n Request captured in NGINX App Protect security log\n API7:2019 - Security Misconfiguration \n Problem Statement: \n Security misconfiguration occurs when security best practices are neglected, leading to vulnerabilities like exposed debug logs, outdated security patches, improper CORS settings, unnecessary allowed HTTP methods, etc. To prevent this, systems must stay up to date with security patches, employ continuous hardening, ensure API communications use secure channels (TLS), etc. \n Example: \n Unnecessary HTTP methods/verbs represent a significant security misconfiguration under the OWASP API Top 10. APIs often expose a range of HTTP methods (such as PUT, DELETE, PATCH) that are not required for the application's functionality. These unused methods, if not properly disabled, can provide attackers with additional attack surfaces, increasing the risk of unauthorized access or unintended actions on the server. Properly limiting and configuring allowed HTTP methods is essential for reducing the potential impact of such security vulnerabilities. Let’s dive into a demo application which has exposed “PUT” method., this method is not required as per the design and attackers can make use of this insecure unintended method to modify the original content. \n \n Solution: \n NGINX App Protect makes it easy to block unnecessary or risky HTTP methods by letting you customize which methods are allowed. By easily configuring a policy to block unauthorized methods, like disabling the PUT method by setting \"$action\": \"delete\", you can reduce potential security risks and strengthen your API protection with minimal effort. \n \n As shown below the attack request is captured in security log which conveys the request was successfully blocked, because of “Illegal method” violation. \n Request captured in NGINX App Protect security log \n API8:2019 - Injection \n Problem Statement: \n Customer login pages without secure coding practices may have flaws. Intruders could use those flaws to exploit credential validation using different types of injections, like SQLi, command injections, etc. In our demo application, we have found an exploit which allows us to bypass credential validation using SQL injection (by using username as “' OR true --” and any password), thereby getting administrative access, as below: \n \n Solution: \n NGINX App Protect has a database of signatures that match this type of SQLi attacks. By configuring the WAF policy in blocking mode, NGINX App Protect can identify and block this attack, as shown below. \n App Protect WAF Policy\n If you check in the security log with this support ID, we can see that request is blocked because of SQL injection risk, as below. \n Request captured in NGINX App Protect security log\n \n API9:2019 - Improper Assets Management \n Problem Statement: \n Improper Asset Management in API security signifies the crucial risk stemming from an incomplete awareness and tracking of an organization's full API landscape, including all environments like development and staging, different versions, both internal and external endpoints, and undocumented or \"shadow\" APIs. This lack of comprehensive inventory leads to an expanded and often unprotected attack surface, as security measures cannot be consistently applied to unknown or unmanaged assets. Consequently, attackers can exploit these overlooked endpoints, potentially find older, less secure versions or access sensitive data inadvertently exposed in non-production environments, thereby undermining overall security posture because you simply cannot protect assets you don't know exist. \n We’re using a flask database application with multiple API endpoints for demonstration. \n As part of managing API assets, the “/v1/admin/users” endpoint in the demo Flask application has been identified as obsolete. The continued exposure of the deprecated “/v1/admin/users” endpoint constitutes an Improper Asset Management vulnerability, creating an unnecessary security exposure that could be leveraged for exploitation. \n <public_ip>/v1/admin/users\n The current endpoint for user listing is “/v2/users”. \n <public_ip>/v2/users with user as admin1\n Solution: \n To mitigate the above vulnerability, we are using NGINX as an API Gateway. The API Gateway acts as a filtering gateway for API incoming traffic, controlling, securing, and routing requests before they reach the backend services. The server’s name used for the above case is “f1-api” which is listening to the public IP where our application is running. \n \n To query the “/v1/admin/users” endpoint, use the curl command as shown below. \n \n Below is the configuration for NGINX as API Gateway, in “api_gateway.conf”, where “/v1/admin/users” endpoint is deprecated. \n \n The “api_json_errors.conf” is configured with error responses as shown below and included in the above “api_gateway.conf”. \n \n Executing the curl command against the endpoint yields an “HTTP 301 Moved Permanently” response. \n https://f1-api/v1/admin/users is deprecated\n API10:2019 - Insufficient Logging & Monitoring \n Problem Statement: \n Appropriate logging and monitoring solutions play a pivotal role in identifying attacks and also in finding the root cause for any security issues. Without these solutions, applications are fully exposed to attackers and SecOps is completely blind to identifying details of users and resources being accessed. \n Solution: \n NGINX provides different options to track logging details of applications for end-to-end visibility of every request both from a security and performance perspective. Users can change configurations as per their requirements and can also configure different logging mechanisms with different levels. Check the links below for more details on logging: \n \n https://www.nginx.com/blog/logging-upstream-nginx-traffic-cdn77/ \n https://www.nginx.com/blog/modsecurity-logging-and-debugging/ \n https://www.nginx.com/blog/using-nginx-logging-for-application-performance-monitoring/ \n https://docs.nginx.com/nginx/admin-guide/monitoring/logging/ \n https://docs.nginx.com/nginx-app-protect-waf/logging-overview/logs-overview/ \n \n Conclusion: \n In short, this article covered some common API vulnerabilities and shows how NGINX App Protect can be used as a mitigation solution to prevent these OWASP API security risks. \n Related resources for more information or to get started: \n \n F5 NGINX App Protect \n OWASP API Security Top 10 2019 \n OWASP API Security Top 10 2023 \n \n ","body@stripHtml({\"removeProcessingText\":true,\"removeSpoilerMarkup\":true,\"removeTocMarkup\":true,\"truncateLength\":-1})@stringLength":"11392","kudosSumWeight":7,"repliesCount":0,"readOnly":false,"images":{"__typename":"AssociatedImageConnection","edges":[{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtMjM4OTZpQTE0Q0ZFMTVFMTBCOEFFMw?revision=54\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDI","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtM2hGd1pF?revision=54\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDM","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtSFA1OHpa?revision=54\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDQ","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtam1vTFIx?revision=54\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDU","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtaU9YQ1dG?revision=54\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDY","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtUTNveEdt?revision=54\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDc","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtMTJXT2VX?revision=54\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDg","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtQVNLUFpr?revision=54\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDk","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtNkptMjNQ?revision=54\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDEw","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtbDFGUXlO?revision=54\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDEx","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtVkVCdGNq?revision=54\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDEy","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtOWFxQmRp?revision=54\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDEz","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtMjYxMjlpM0Y0QkY4NTRBM0JBRkYyRA?revision=54\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE0","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtMjYxMzBpMEYwNzM4ODY5M0VGMEVBQg?revision=54\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE1","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtMjYxMzhpRTc5QTFGODZENDA1MDgwRg?revision=54\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE2","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtdHJDRDBk?revision=54\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE3","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtblBiMVRI?revision=54\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE4","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtcXAzcUFn?revision=54\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDE5","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtbVU4MEg3?revision=54\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDIw","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtWGZkOURX?revision=54\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDIx","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtRFluak1Z?revision=54\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDIy","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtYnc0aEdj?revision=54\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDIz","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtQ0ZueUlP?revision=54\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDI0","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtYVhQNTVD?revision=54\"}"}},{"__typename":"AssociatedImageEdge","cursor":"MjUuM3wyLjF8b3wyNXxfTlZffDI1","node":{"__ref":"AssociatedImage:{\"url\":\"https://community.f5.com/t5/s/zihoc95639/images/bS0zMjMyNTQtY3kyMzAx?revision=54\"}"}}],"totalCount":37,"pageInfo":{"__typename":"PageInfo","hasNextPage":true,"endCursor":"MjUuM3wyLjF8b3wyNXxfTlZffDI1","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},"Category:category:top":{"__typename":"Category","id":"category:top","nodeType":"category"},"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":"mostViewed","tagName":"nginx"},"buildId":"-gVUpXaWnPcjlrLJZ92B7","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":[]}