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 +4/−0
- LICENSE +1/−1
- NgxExport/Healthcheck.hs +106/−6
- ngx-export-healthcheck.cabal +8/−3
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