diff options
Diffstat (limited to 'modules/pkgs')
-rw-r--r-- | modules/pkgs/xinclude2nix/default.nix | 60 | ||||
-rw-r--r-- | modules/pkgs/xinclude2nix/xinclude2nix.hs | 46 |
2 files changed, 106 insertions, 0 deletions
diff --git a/modules/pkgs/xinclude2nix/default.nix b/modules/pkgs/xinclude2nix/default.nix new file mode 100644 index 0000000..09a9ab3 --- /dev/null +++ b/modules/pkgs/xinclude2nix/default.nix @@ -0,0 +1,60 @@ +{ runCommand, haskellPackages }: + +/* + Given a list of XML files, produces a Nix file with a list of files included + with the XInclude mechanism. The file produced can be imported into other + Nix files. This requires read-write mode of evaluation. + + Use case: XML config files with portions of sensitive data (secrets, keys), + merged in runtime. With this package, deployment tools like NixOps can be + taught to extract keys and deploy them automatically. + + + Example of input file (for Jenkins): + + <?xml version="1.0" encoding="UTF-8"?> + <hudson xmlns:xi="http://www.w3.org/2001/XInclude"> + <useSecurity>true</useSecurity> + <authorizationStrategy class="hudson.security.ProjectMatrixAuthorizationStrategy"> + <permission>hudson.model.Hudson.Read:ip1981</permission> + <permission>hudson.model.Item.Build:ip1981</permission> + <permission>hudson.model.Item.Cancel:ip1981</permission> + <permission>hudson.model.Item.Read:ip1981</permission> + <permission>hudson.model.Hudson.Administer:ip1981</permission> + </authorizationStrategy> + <securityRealm class="org.jenkinsci.plugins.GithubSecurityRealm"> + <clientID>XXXXXXXXXXXXXXXXXXX</clientID> + <xi:include href="/run/keys/github-oauth-XXXXXXXXXXXXXXXXXXX.xml"/> + <oauthScopes>read:org,user:email</oauthScopes> + </securityRealm> + </hudson> + + + Corresponding output file (/nix/store/abc...xyz-xinclude.nix): + + ["/run/keys/github-oauth-XXXXXXXXXXXXXXXXXXX.xml"] + +*/ + +# XXX: either string or list of strings +xmlFiles: + +let + + inherit (builtins) toString; + + xinclude2nix = + let + deps = hpkgs: with hpkgs; [ hxt ]; + ghc = "${haskellPackages.ghcWithPackages deps}/bin/ghc -Wall -static"; + in runCommand "xinclude2nix" {} '' + ${ghc} -o $out ${./xinclude2nix.hs} + ''; + +in runCommand "xinclude.nix" {} '' + echo ${xinclude2nix} ${toString xmlFiles} >&2 + ${xinclude2nix} ${toString xmlFiles} > $out + echo -n "$out: " >&2 + cat "$out" >&2 +'' + diff --git a/modules/pkgs/xinclude2nix/xinclude2nix.hs b/modules/pkgs/xinclude2nix/xinclude2nix.hs new file mode 100644 index 0000000..49d34ca --- /dev/null +++ b/modules/pkgs/xinclude2nix/xinclude2nix.hs @@ -0,0 +1,46 @@ +{-# LANGUAGE Arrows #-} + +{- + Takes a list of XML files + Parses them for xi:xinclude elements + Extract included files + Prints list of included files +-} + +module Main where + +import Data.List (intercalate, isPrefixOf, stripPrefix) +import Data.Maybe (fromMaybe) +import System.Environment (getArgs) +import Text.XML.HXT.Core ( (>>>), deep, getAttrValue, hasAttr, hasName, + isElem, readDocument, returnA, runX) + +getXIncludes :: String -> IO [String] +getXIncludes xmlFileName = runX $ readDocument [] xmlFileName + >>> deep (isElem >>> hasName "xi:include" >>> hasAttr "href") >>> + proc d -> do + href <- getAttrValue "href" -< d + returnA -< href + +getFiles :: [String] -> [String] +getFiles = map stripScheme . filter isFile + where + fileScheme = "file://" + isFile s = "/" `isPrefixOf` s || (fileScheme `isPrefixOf` s) + stripScheme u = fromMaybe u (stripPrefix fileScheme u) + +unique :: [String] -> [String] +unique [] = [] +unique (x:xs) + | x `elem` xs = unique xs + | otherwise = x:unique xs + +toNix :: [String] -> String +toNix ss = "[" ++ intercalate " " (map show ss) ++ "]" + +main :: IO () +main = do + paths <- getArgs + includedFiles <- unique . getFiles . concat <$> mapM getXIncludes paths + putStrLn $ toNix includedFiles + |