packages feed

ngx-export-healthcheck 1.6.2 → 1.6.3

raw patch · 4 files changed

+119/−10 lines, 4 filesdep +crypton-x509-storePVP ok

version bump matches the API change (PVP)

Dependencies added: crypton-x509-store

API changes (from Hackage documentation)

+ NgxExport.Healthcheck: useCustomCAStore :: CertificateStore -> IO ()

Files

Changelog.md view
@@ -1,3 +1,7 @@+### 1.6.3++- Added ability to tweak CA store when running health checks over *https*.+ ### 1.6.2  - Fixed validation of server certificates by name (versions *1.6* and *1.6.1*
LICENSE view
@@ -1,4 +1,4 @@-Copyright 2022-2023, Alexey Radkov. All rights reserved.+Copyright 2022-2024, Alexey Radkov. All rights reserved.  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
NgxExport/Healthcheck.hs view
@@ -5,7 +5,7 @@ ----------------------------------------------------------------------------- -- | -- Module      :  NgxExport.Healthcheck--- Copyright   :  (c) Alexey Radkov 2022-2023+-- Copyright   :  (c) Alexey Radkov 2022-2024 -- License     :  BSD-style -- -- Maintainer  :  alexey.radkov@gmail.com@@ -16,7 +16,14 @@ -- ----------------------------------------------------------------------------- -module NgxExport.Healthcheck (module Types) where+module NgxExport.Healthcheck (+    -- * Type declarations+                              module Types+#ifdef HEALTHCHECK_HTTPS+    -- * Use a custom CA store+                             ,useCustomCAStore+#endif+                             ) where  import           NgxExport import           NgxExport.Healthcheck.Types as Types@@ -71,8 +78,10 @@ import           Network.TLS hiding (HashSHA256) import           Network.TLS.Extra.Cipher import           System.X509 (getSystemCertificateStore)+import           Data.X509.CertificateStore import qualified Data.X509.Validation as X509 import           Data.X509 (HashALG (..))+import           Control.Applicative #endif  #ifdef SNAP_STATS_SERVER@@ -147,6 +156,97 @@     c_healthcheck_srv :: Ptr () -> Ptr () -> CString -> Ptr CString ->                          Ptr CSize -> IO CIntPtr +customCAStore :: IORef (Maybe CertificateStore)+customCAStore = unsafePerformIO $ newIORef Nothing+{-# NOINLINE customCAStore #-}++-- | Use a custom CA store in health checks over https.+--+-- When doing health checks over https, it's sometimes required to tweak the+-- location of the trusted certificates store. This functions implements such a+-- tweak when it's run from the initialization hook.+--+-- ==== __Example 1: use a CA store accessible in Nginx worker processes__+-- ===== File /ngx_healthcheck.hs/+-- @+-- {-\# LANGUAGE TemplateHaskell \#-}+--+-- module NgxHealthcheck where+--+-- import           NgxExport+-- import           NgxExport.Healthcheck+-- import           System.Environment+-- import           Data.Maybe+-- import           Data.X509.CertificateStore+--+-- customCAStore :: IO ()+-- customCAStore = do+--     args \<- dropWhile (\/= \"--ca\") \<$\> 'System.Environment.getArgs'+--     case args of+--         _ : ca : _ -> do+--             store \<- fromJust \<$\> 'readCertificateStore' ca+--             store \`seq\` __/useCustomCAStore/__ store+--         _ -> return ()+-- 'ngxExportInitHook' \'customCAStore+-- @+--+-- ===== File /nginx.conf/ (a fragment)+-- @+--     haskell program_options --ca \/path\/to\//ca-dir-or-file/;+--     haskell load \/var\/lib\/nginx\/ngx_healthcheck.so;+-- @+--+-- ==== __Example 2: use a CA store accessible only in Nginx master process__+--+-- In this case, the /mread/ trick is used to make Nginx master process+-- substitute the file content in place of the path contained in the argument+-- of /haskell program_options/ which follows /--mread:ca/.+--+-- ===== File /ngx_healthcheck.hs/+-- @+-- {-\# LANGUAGE TemplateHaskell \#-}+--+-- module NgxHealthcheck where+--+-- import           NgxExport+-- import           NgxExport.Healthcheck+-- import           Data.ByteString (ByteString)+-- import qualified Data.ByteString.Char8 as C8+-- import           System.Environment+-- import           Data.Maybe+-- import           Data.Either+-- import           Data.X509+-- import           Data.X509.CertificateStore+-- import           Data.PEM+--+-- mkCertificateStore :: ByteString -> Maybe 'CertificateStore'+-- mkCertificateStore ca = do+--     parsed <- either (return Nothing) (Just . rights . map getCert) $+--         pemParseBS ca+--     Just $ 'makeCertificateStore' parsed+--     where getCert = decodeSignedCertificate . pemContent+--+-- customCAStore :: IO ()+-- customCAStore = do+--     args \<- dropWhile (\/= \"--/mread:/ca\") \<$\> 'System.Environment.getArgs'+--     case args of+--         _ : ca : _ -> do+--             let store = fromJust $ mkCertificateStore $ C8.pack ca+--             store \`seq\` __/useCustomCAStore/__ store+--         _ -> return ()+-- 'ngxExportInitHook' \'customCAStore+-- @+--+-- ===== File /nginx.conf/ (a fragment)+-- @+--     haskell program_options --/mread:/ca \/path\/to\//ca-file/;+--     haskell load \/var\/lib\/nginx\/ngx_healthcheck.so;+-- @+--+-- @since 1.6.3+useCustomCAStore :: CertificateStore -> IO ()+useCustomCAStore = writeIORef customCAStore . Just+ mkHttpsManager :: [Upstream] -> Maybe PeerHostName -> IO () mkHttpsManager us hname = do     hnames <-@@ -177,14 +277,14 @@     man <- mapM (\name -> (name, ) <$> mkManager name) hnames     atomicModifyIORef' httpsManager $ (, ()) . (`HM.union` HM.fromList man)     where mkManager name = do-              systemCAStore <- getSystemCertificateStore+              caStore <- do { Just v <- readIORef customCAStore; return v }+                            <|> getSystemCertificateStore               let (T.unpack -> h, T.encodeUtf8 -> p) =-                      second (fromMaybe "" . fmap snd . T.uncons) $-                          T.break (':' ==) name+                      second (maybe "" snd . T.uncons) $ T.break (':' ==) name                   validateName = const . hookValidateName X509.defaultHooks                   defaultParams = (defaultParamsClient h p)                       { clientShared = def-                          { sharedCAStore = systemCAStore }+                          { sharedCAStore = caStore }                       , clientHooks = def                           { onServerCertificate = X509.validate HashSHA256                               X509.defaultHooks
ngx-export-healthcheck.cabal view
@@ -1,5 +1,5 @@ name:                  ngx-export-healthcheck-version:               1.6.2+version:               1.6.3 synopsis:              Active health checks and monitoring of Nginx upstreams description:           Active health checks and monitoring of Nginx upstreams.         .@@ -9,15 +9,19 @@ homepage:              http://github.com/lyokha/nginx-healthcheck-plugin license:               BSD3 license-file:          LICENSE-extra-source-files:    Changelog.md+extra-doc-files:       Changelog.md author:                Alexey Radkov <alexey.radkov@gmail.com> maintainer:            Alexey Radkov <alexey.radkov@gmail.com> stability:             stable-copyright:             2022-2023 Alexey Radkov+copyright:             2022-2024 Alexey Radkov category:              Network build-type:            Simple cabal-version:         1.20 +source-repository head+  type:                git+  location:            https://github.com/lyokha/nginx-healthcheck-plugin.git+ flag SnapStatsServer   description:         Build Snap server to collect stats. @@ -53,6 +57,7 @@                      , data-default-class                      , crypton-connection                      , crypton-x509+                     , crypton-x509-store                      , crypton-x509-system                      , crypton-x509-validation                      , tls >= 1.4.0