Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FQDN and TLS trust management (example extension) #28

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# mimick use case where users are expected to boostrap their dev ca
# this is also better for testing devhsell ca bootstrapping
dev-ca
3 changes: 2 additions & 1 deletion default.nix
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
{ nixpkgs ? import ./nix/nixpkgs.nix
, system ? builtins.currentSystem
, overlays ? [ ]
}:
import nixpkgs {
inherit system;
overlays = [ (import ./overlay.nix) ];
overlays = [ (import ./overlay.nix) ] ++ overlays;
}
30 changes: 30 additions & 0 deletions devshell.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,33 @@ help = "github utility"
name = "hub"
package = "gitAndTools.hub"
category = "utilites"


# ============================================================================
# Example of custom extensions NOT part of devshell, see also:
# ============================================================================
# ./default.nix
# ./shell.nix
# ./extensions/*
# ============================================================================

[extensions]
# This setting helps to add a project's shared *development* root CA
# to host's local trust stores by instrumenting the mkcert third party tool.
# Defining this section also adds `mkcert` to the available packages.
# Set to the path where mkcert-generated CAROOT files are expected to exist
#
# NOTES:
# - be careful to only put *development* certificates under version control
# - create those files with the devshell generated *-install-CA command
# - optionally put this path under .gitignore, if you want users to
# generate certificates themselves on first clone (using *-install-CA)
dev-ca-path = "./dev-ca"

# These settings help to manage local DNS overrides via
# instrumentation of the hostcl third party tool.
# Defining this section also adds `hostctl` to the available packages.
[extensions.static-dns]
"test.domain.local" = "172.0.0.1"
"shared.domain.link-local" = "169.254.0.5"

40 changes: 40 additions & 0 deletions extensions/hostctl/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{ buildGoModule, fetchFromGitHub, lib, installShellFiles }:

buildGoModule rec {
pname = "hostctl";
version = "1.0.14";

src = fetchFromGitHub {
owner = "guumaster";
repo = pname;
rev = "v${version}";
sha256 = "02bjii97l4fy43v2rb93m9b0ad8y6mjvbvp4sz6a5n0w9dm1z1q9";
};

vendorSha256 = "1lqk3cda0frqp2vwkqa4b3xkdw814wgkbr7g9r2mwxn85fpdcq5c";

doCheck = false;
buildFlagsArray = [ "-ldflags=-s -w -X github.com/guumaster/hostctl/cmd/hostctl/actions.version=${version}" ];

nativeBuildInputs = [ installShellFiles ];
postInstall = ''
$out/bin/hostctl completion bash > hostctl.bash
$out/bin/hostctl completion zsh > hostctl.zsh
installShellCompletion hostctl.{bash,zsh}
# replace above by following once merged https://github.com/NixOS/nixpkgs/pull/83630
# installShellCompletion --cmd hostctl \
# --bash <($out/bin/hostctl completion bash) \
# --zsh <($out/bin/hostctl completion zsh)
'';

meta = with lib; {
description = "Your dev tool to manage /etc/hosts like a pro!";
longDescription = ''
This tool gives you more control over the use of your hosts file.
You can have multiple profiles and switch them on/off as you need.
'';
homepage = "https://guumaster.github.io/hostctl/";
license = licenses.mit;
maintainers = with maintainers; [ blaggacao ];
};
}
120 changes: 120 additions & 0 deletions extensions/options.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
{ lib, pkgs, config, ... }:
with lib;
let
inherit (config)
name
;
inherit (config.extensions)
static-dns
dev-ca-path
;

installProjectCA = {
name = "ca-install";
help = "install dev CA";
category = "host state";
package = pkgs.mkcert;
command = ''
echo "$(tput bold)Installing ${name}'s dev CA into local trust stores via mkcert command ...$(tput sgr0)"
export CAROOT=$DEVSHELL_ROOT${dev-ca-path}
${pkgs.mkcert}/bin/mkcert -install
'';
};
uninstallProjectCA = {
name = "ca-uninstall";
help = "uninstall dev CA";
category = "host state";
package = pkgs.mkcert;
command = ''
echo "$(tput bold)Purging ${name}'s dev CA from local trust stores via mkcert command ...$(tput sgr0)"
export CAROOT=$DEVSHELL_ROOT${dev-ca-path}
${pkgs.mkcert}/bin/mkcert -uninstall
'';
};

etcHosts =
pkgs.writeText "${name}-etchosts"
(
lib.concatStringsSep "\n"
(lib.mapAttrsToList (name: value: value + " " + name) static-dns)
);
# since this temporarily modifies /etc/hosts, use of sudo can't be avoided
fqdnsActivate = {
name = "dns-activate";
category = "host state";
help = "activate pre-configured static dns";
package = pkgs.hostctl;
command = ''
echo "$(tput bold)Installing ${name}'s static local DNS resolution via hostctl command ...$(tput sgr0)"
sudo ${pkgs.hostctl}/bin/hostctl add ${name} --from ${etcHosts}
'';
};
fqdnsDeactivate = {
name = "dns-deactivate";
category = "host state";
help = "deactivate pre-configured static dns";
package = pkgs.hostctl;
command = ''
echo "$(tput bold)Purging ${name}'s static local DNS resolution via hostctl command ...$(tput sgr0)"
sudo ${pkgs.hostctl}/bin/hostctl remove ${name}
'';
};
extensionOptions = {
dev-ca-path = mkOption {
type = types.str;
default = "";
description = ''
Path to a development CA.

Users can load/unload this dev CA easily and cleanly into their local
trust stores via a wrapper around mkcert third party tool so that browsers
and other tools would accept issued certificates under this CA as valid.

Use cases:
- Ship static dev certificates under version control and make them trusted
on user machines: add the rootCA under version control alongside your
dev certificates.
- Provide users with easy and reliable CA bootstrapping through the mkcert
command: exempt this path from version control via .gitignore and have
users easily and reliably bootstrap a dev CA infrastructure on first use.
'';
};
static-dns = mkOption {
type = types.attrs;
default = { };
description = ''
A list of static DNS entries, for which to enable instrumentation.

Users can enable/disable listed static DNS easily and cleanly
via a wrapper around the hostctl third party tool.
'';
example = {
"test.domain.local" = "172.0.0.1";
"shared.domain.link-local" = "169.254.0.5";
};
};
};
in
{
options = {
extensions = mkOption {
type = types.submodule { options = extensionOptions; };
default = [ ];
description = ''
Custom extensions to devshell.
'';
};
};
config = {
commands =
(
if static-dns == null || static-dns == "" then [ ]
else [ fqdnsActivate fqdnsDeactivate ]
) ++
(
if dev-ca-path == null || dev-ca-path == "" then [ ]
else [ installProjectCA uninstallProjectCA ]
);
};
bash.extra = "export CAROOT=$DEVSHELL_ROOT/${dev-ca-path}";
}
4 changes: 4 additions & 0 deletions extensions/overlay.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
final: prev:
{
hostctl = prev.callPackage ./hostctl { };
}
7 changes: 4 additions & 3 deletions mkDevShell/options.nix
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ let

opCat = { name, value }:
let
opCmd = { name, help, ...}:
opCmd = { name, help, ... }:
let
len = maxCommandLength - (builtins.stringLength name);
in
Expand All @@ -57,7 +57,7 @@ let
else
"${pad name len} - ${help}";
in
"\n[${name}]\n" + builtins.concatStringsSep "\n" (map opCmd value);
"\n[${name}]\n" + builtins.concatStringsSep "\n" (map opCmd value);
in
builtins.concatStringsSep "\n" (map opCat commandByCategoriesSorted)
;
Expand Down Expand Up @@ -226,7 +226,8 @@ in
];

packages =
builtins.filter (x: x != null)
builtins.filter
(x: x != null)
(map (x: x.package) config.commands);
};
}
12 changes: 10 additions & 2 deletions shell.nix
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
#!/usr/bin/env nix-build
# Used to test the shell
{ pkgs ? import ./. { } }:
pkgs.mkDevShell.fromTOML ./devshell.toml
{ pkgs ? import ./. {
overlays = [ (import ./extensions/overlay.nix) ];
}
}:
pkgs.mkDevShell {
imports = [
(pkgs.mkDevShell.importTOML ./devshell.toml)
./extensions/options.nix
];
}