Skip to content
This repository has been archived by the owner on Jul 14, 2022. It is now read-only.

Commit

Permalink
Added a subcommmand to generate ssl certificates using letsencrypt ht…
Browse files Browse the repository at this point in the history
…tp challenges handled by the frontend proxy
  • Loading branch information
timbod7 committed Nov 8, 2018
1 parent c8eb258 commit 18799d1
Show file tree
Hide file tree
Showing 6 changed files with 175 additions and 37 deletions.
24 changes: 22 additions & 2 deletions adl/config.adl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ struct ToolConfig {
FilePath releasesDir = "/opt/releases";
FilePath contextCache = "/opt/etc/deployment";
FilePath logFile = "/opt/var/log/hx-deploy-tool.log";
FilePath letsencryptPrefixDir = "/opt";
FilePath letsencryptWwwDir = "/opt/var/www";

/// If the deploy tool needs to generate an SSL certificate
/// using letsencrypt, it will be called this.
String autoCertName = "hxdeploytoolcert";
String autoCertContactEmail = "";

/// The storage location for release zip files
BlobStoreConfig releases;
Expand Down Expand Up @@ -57,13 +64,26 @@ union MachineLabel {
struct EndPoint {
EndPointLabel label;
String serverName;
String sslCertDir;
EndPointType etype;
};

union EndPointType {
Void httpOnly;
Void httpsWithRedirect;
SslCertMode httpsWithRedirect;
};

union SslCertMode {
/// Use letsencrypt to generate a certificate
Void generated;

/// Use the existing certificate from the given file system
/// paths
SslCertPaths explicit;
};

struct SslCertPaths {
FilePath sslCertificate;
FilePath sslCertificateKey;
};

struct DeployContextFile
Expand Down
2 changes: 2 additions & 0 deletions adl/config.adl-hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ annotation EndPointType HaskellFieldPrefix "ep_";
annotation ToolConfig HaskellFieldPrefix "tc_";
annotation ProxyModeConfig HaskellFieldPrefix "pm_";
annotation LetsEncryptConfig HaskellFieldPrefix "lec_";
annotation SslCertMode HaskellFieldPrefix "scm_";
annotation SslCertPaths HaskellFieldPrefix "scp_";
};
68 changes: 59 additions & 9 deletions src/ADL/Config.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ module ADL.Config(
LetsEncryptConfig(..),
MachineLabel(..),
ProxyModeConfig(..),
SslCertMode(..),
SslCertPaths(..),
ToolConfig(..),
Verbosity(..),
) where
Expand Down Expand Up @@ -84,46 +86,43 @@ instance AdlValue DeployMode where
data EndPoint = EndPoint
{ ep_label :: ADL.Types.EndPointLabel
, ep_serverName :: T.Text
, ep_sslCertDir :: T.Text
, ep_etype :: EndPointType
}
deriving (Prelude.Eq,Prelude.Ord,Prelude.Show)

mkEndPoint :: ADL.Types.EndPointLabel -> T.Text -> T.Text -> EndPointType -> EndPoint
mkEndPoint label serverName sslCertDir etype = EndPoint label serverName sslCertDir etype
mkEndPoint :: ADL.Types.EndPointLabel -> T.Text -> EndPointType -> EndPoint
mkEndPoint label serverName etype = EndPoint label serverName etype

instance AdlValue EndPoint where
atype _ = "config.EndPoint"

jsonGen = genObject
[ genField "label" ep_label
, genField "serverName" ep_serverName
, genField "sslCertDir" ep_sslCertDir
, genField "etype" ep_etype
]

jsonParser = EndPoint
<$> parseField "label"
<*> parseField "serverName"
<*> parseField "sslCertDir"
<*> parseField "etype"

data EndPointType
= Ep_httpOnly
| Ep_httpsWithRedirect
| Ep_httpsWithRedirect SslCertMode
deriving (Prelude.Eq,Prelude.Ord,Prelude.Show)

instance AdlValue EndPointType where
atype _ = "config.EndPointType"

jsonGen = genUnion (\jv -> case jv of
Ep_httpOnly -> genUnionVoid "httpOnly"
Ep_httpsWithRedirect -> genUnionVoid "httpsWithRedirect"
Ep_httpsWithRedirect v -> genUnionValue "httpsWithRedirect" v
)

jsonParser
= parseUnionVoid "httpOnly" Ep_httpOnly
<|> parseUnionVoid "httpsWithRedirect" Ep_httpsWithRedirect
<|> parseUnionValue "httpsWithRedirect" Ep_httpsWithRedirect
<|> parseFail "expected a EndPointType"

data LetsEncryptConfig = LetsEncryptConfig
Expand Down Expand Up @@ -204,10 +203,53 @@ instance AdlValue ProxyModeConfig where
<*> parseFieldDef "dynamicPortRange" ((,) 8000 8100)
<*> parseFieldDef "slaveLabel" MachineLabel_ec2InstanceId

data SslCertMode
= Scm_generated
| Scm_explicit SslCertPaths
deriving (Prelude.Eq,Prelude.Ord,Prelude.Show)

instance AdlValue SslCertMode where
atype _ = "config.SslCertMode"

jsonGen = genUnion (\jv -> case jv of
Scm_generated -> genUnionVoid "generated"
Scm_explicit v -> genUnionValue "explicit" v
)

jsonParser
= parseUnionVoid "generated" Scm_generated
<|> parseUnionValue "explicit" Scm_explicit
<|> parseFail "expected a SslCertMode"

data SslCertPaths = SslCertPaths
{ scp_sslCertificate :: ADL.Types.FilePath
, scp_sslCertificateKey :: ADL.Types.FilePath
}
deriving (Prelude.Eq,Prelude.Ord,Prelude.Show)

mkSslCertPaths :: ADL.Types.FilePath -> ADL.Types.FilePath -> SslCertPaths
mkSslCertPaths sslCertificate sslCertificateKey = SslCertPaths sslCertificate sslCertificateKey

instance AdlValue SslCertPaths where
atype _ = "config.SslCertPaths"

jsonGen = genObject
[ genField "sslCertificate" scp_sslCertificate
, genField "sslCertificateKey" scp_sslCertificateKey
]

jsonParser = SslCertPaths
<$> parseField "sslCertificate"
<*> parseField "sslCertificateKey"

data ToolConfig = ToolConfig
{ tc_releasesDir :: ADL.Types.FilePath
, tc_contextCache :: ADL.Types.FilePath
, tc_logFile :: ADL.Types.FilePath
, tc_letsencryptPrefixDir :: ADL.Types.FilePath
, tc_letsencryptWwwDir :: ADL.Types.FilePath
, tc_autoCertName :: T.Text
, tc_autoCertContactEmail :: T.Text
, tc_releases :: BlobStoreConfig
, tc_deployContext :: BlobStoreConfig
, tc_deployContextFiles :: [DeployContextFile]
Expand All @@ -216,7 +258,7 @@ data ToolConfig = ToolConfig
deriving (Prelude.Eq,Prelude.Ord,Prelude.Show)

mkToolConfig :: BlobStoreConfig -> BlobStoreConfig -> [DeployContextFile] -> ToolConfig
mkToolConfig releases deployContext deployContextFiles = ToolConfig "/opt/releases" "/opt/etc/deployment" "/opt/var/log/hx-deploy-tool.log" releases deployContext deployContextFiles DeployMode_select
mkToolConfig releases deployContext deployContextFiles = ToolConfig "/opt/releases" "/opt/etc/deployment" "/opt/var/log/hx-deploy-tool.log" "/opt" "/opt/var/www" "hxdeploytoolcert" "" releases deployContext deployContextFiles DeployMode_select

instance AdlValue ToolConfig where
atype _ = "config.ToolConfig"
Expand All @@ -225,6 +267,10 @@ instance AdlValue ToolConfig where
[ genField "releasesDir" tc_releasesDir
, genField "contextCache" tc_contextCache
, genField "logFile" tc_logFile
, genField "letsencryptPrefixDir" tc_letsencryptPrefixDir
, genField "letsencryptWwwDir" tc_letsencryptWwwDir
, genField "autoCertName" tc_autoCertName
, genField "autoCertContactEmail" tc_autoCertContactEmail
, genField "releases" tc_releases
, genField "deployContext" tc_deployContext
, genField "deployContextFiles" tc_deployContextFiles
Expand All @@ -235,6 +281,10 @@ instance AdlValue ToolConfig where
<$> parseFieldDef "releasesDir" "/opt/releases"
<*> parseFieldDef "contextCache" "/opt/etc/deployment"
<*> parseFieldDef "logFile" "/opt/var/log/hx-deploy-tool.log"
<*> parseFieldDef "letsencryptPrefixDir" "/opt"
<*> parseFieldDef "letsencryptWwwDir" "/opt/var/www"
<*> parseFieldDef "autoCertName" "hxdeploytoolcert"
<*> parseFieldDef "autoCertContactEmail" ""
<*> parseField "releases"
<*> parseField "deployContext"
<*> parseField "deployContextFiles"
Expand Down
14 changes: 11 additions & 3 deletions src/Commands/ProxyMode.hs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ module Commands.ProxyMode(
connect,
disconnect,
slaveUpdate,
restartProxy
restartProxy,
generateSslCertificate
) where

import qualified ADL.Core.StringMap as SM
Expand All @@ -29,7 +30,7 @@ import ADL.State(State(..), Deploy(..))
import ADL.Types(EndPointLabel, DeployLabel)
import Util(unpackRelease,fetchDeployContext, checkReleaseExists)
import Commands.ProxyMode.Types
import Commands.ProxyMode.LocalState(localState, restartLocalProxy)
import Commands.ProxyMode.LocalState(localState, restartLocalProxy, generateLocalSslCertificate)
import Commands.ProxyMode.RemoteState(remoteState, writeSlaveState, masterS3Path)
import Control.Concurrent(threadDelay)
import Control.Exception(SomeException)
Expand Down Expand Up @@ -66,7 +67,7 @@ showStatus showSlaves = do
for_ (pmEndPoints pm) $ \ep -> do
let etype = case ep_etype ep of
Ep_httpOnly -> "(" <> ep_serverName ep <> ":80)"
Ep_httpsWithRedirect -> "(" <> ep_serverName ep <> ":80,442)"
Ep_httpsWithRedirect _ -> "(" <> ep_serverName ep <> ":80,442)"
let connected = case SM.lookup (ep_label ep) (s_connections state) of
Nothing -> "(not connected)"
Just deployLabel -> deployLabel
Expand Down Expand Up @@ -212,6 +213,13 @@ restartProxy = do
Nothing -> restartLocalProxy
_ -> return ()

generateSslCertificate :: IOR ()
generateSslCertificate = do
pm <- getProxyModeConfig
case pm_remoteStateS3 pm of
Nothing -> generateLocalSslCertificate
_ -> return ()


getSlaveLabel :: IOR T.Text
getSlaveLabel = do
Expand Down
Loading

0 comments on commit 18799d1

Please sign in to comment.