Skip to content

Commit

Permalink
ssl: Add initial support for supplying ssl certs
Browse files Browse the repository at this point in the history
Signed-off-by: Joshua Hesketh <[email protected]>
  • Loading branch information
jhesketh committed Dec 14, 2021
1 parent fbe895e commit 4eda45d
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 3 deletions.
12 changes: 10 additions & 2 deletions src/aquarium.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,16 @@ async def main_loop(self):

async def start_uvicorn(self):
logger.debug("Starting uvicorn")
# TODO(jhesketh): Check if we need https or not
uvicorn_config = Config(self.app, host="0.0.0.0", port=80)
if self.gstate.config.options.ssl.use_ssl:
uvicorn_config = Config(
self.app,
host="0.0.0.0",
port=443,
ssl_keyfile=self.gstate.config.ssl_keypath,
ssl_certfile=self.gstate.config.ssl_certpath,
)
else:
uvicorn_config = Config(self.app, host="0.0.0.0", port=80)
self.uvicorn = AquariumUvicorn(config=uvicorn_config)
asyncio.create_task(self.uvicorn.serve())
# TODO(jhesketh): When in https mode, test if running a second uvicorn
Expand Down
31 changes: 31 additions & 0 deletions src/gravel/api/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

from gravel.api import jwt_auth_scheme
from gravel.cephadm.models import VolumeDeviceModel
from gravel.controllers.config import SSLOptionsModel
from gravel.controllers.gstate import GlobalState
from gravel.controllers.inventory.nodeinfo import NodeInfoModel
from gravel.controllers.nodes.deployment import NodeStageEnum
Expand Down Expand Up @@ -51,6 +52,12 @@ class EventModel(BaseModel):
message: str


class SSLConfigModel(BaseModel):
use_ssl: bool = Field(False, title="Whether https is enabled.")
key_contents: str = Field(title="The SSL private key.")
cert_contents: str = Field(title="The SSL certificate.")


@router.get(
"/volumes",
name="Obtain local volumes",
Expand Down Expand Up @@ -182,6 +189,30 @@ async def get_events(
return [EventModel.parse_obj(event) for event in events]


@router.get(
"/ssl",
name="Get current SSL configuration",
response_model=SSLOptionsModel,
)
async def get_ssl_config(
request: Request, _: Callable = Depends(jwt_auth_scheme)
) -> SSLOptionsModel:
return request.app.state.gstate.config.options.ssl


@router.post("/ssl", name="Update SSL configuration")
async def apply_ssl_config(
request: Request,
req_params: SSLConfigModel,
_: Callable = Depends(jwt_auth_scheme),
) -> bool:
request.app.state.gstate.config.write_ssl_key(req_params.key_contents)
request.app.state.gstate.config.write_ssl_cert(req_params.cert_contents)
request.app.state.gstate.config.options.ssl.use_ssl = req_params.use_ssl
request.app.state.gstate.request_restart_uvicorn()
return request.app.state.gstate.config.saveConfig()


@router.post("/reboot", name="Reboot the system")
async def reboot(_: Callable = Depends(jwt_auth_scheme)) -> None:
ret, _, stderr = await aqr_run_cmd(["systemctl", "reboot"]) # type: ignore
Expand Down
21 changes: 20 additions & 1 deletion src/gravel/controllers/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ def get_image(self) -> str:
return f"{self.registry}/{self.image}"


class SSLOptionsModel(BaseModel):
use_ssl: bool = Field(False, title="Whether https is enabled.")


class OptionsModel(BaseModel):
inventory: InventoryOptionsModel = Field(InventoryOptionsModel())
storage: StorageOptionsModel = Field(StorageOptionsModel())
Expand All @@ -85,6 +89,7 @@ class OptionsModel(BaseModel):
network: NetworkOptionsModel = Field(NetworkOptionsModel())
auth: AuthOptionsModel = Field(AuthOptionsModel())
containers: ContainersOptionsModel = Field(ContainersOptionsModel())
ssl: SSLOptionsModel = Field(SSLOptionsModel())


class ConfigModel(BaseModel):
Expand All @@ -99,6 +104,8 @@ def __init__(self, path: Optional[str] = None):
path = _get_default_confdir()
self._confdir = Path(path)
self.confpath = self._confdir.joinpath(Path("config.json"))
self.ssl_keypath = self._confdir.joinpath(Path("ssl_key.pem"))
self.ssl_certpath = self._confdir.joinpath(Path("ssl_cert.pem"))
logger.debug(f"Aquarium config dir: {self._confdir}")

self._confdir.mkdir(0o700, parents=True, exist_ok=True)
Expand Down Expand Up @@ -133,9 +140,21 @@ def _registry_config_from_env(self):
if len(keys) > 0:
logger.warning("Using custom registry config from environment")

def _saveConfig(self, conf: ConfigModel) -> None:
def _saveConfig(self, conf: ConfigModel) -> bool:
logger.debug(f"Writing Aquarium config: {self.confpath}")
self.confpath.write_text(conf.json(indent=2))
return True

def saveConfig(self) -> bool:
return self._saveConfig(self.config)

def write_ssl_key(self, contents: str) -> None:
self.ssl_keypath.write_text(contents)
self.ssl_keypath.chmod(0o600)

def write_ssl_cert(self, contents: str) -> None:
self.ssl_certpath.write_text(contents)
self.ssl_certpath.chmod(0o644)

@property
def options(self) -> OptionsModel:
Expand Down

0 comments on commit 4eda45d

Please sign in to comment.