at 18.09-beta 6.0 kB view raw
1{ 2 pkgs ? import <nixpkgs> {}, 3 externalDomain ? "myawesomecluster.cluster.yourdomain.net", 4 serviceClusterIp ? "10.0.0.1", 5 kubelets, 6 ... 7}: 8let 9 runWithCFSSL = name: cmd: 10 let secrets = pkgs.runCommand "${name}-cfss.json" { 11 buildInputs = [ pkgs.cfssl pkgs.jq ]; 12 outputs = [ "out" "cert" "key" "csr" ]; 13 } 14 '' 15 ( 16 echo "${cmd}" 17 cfssl ${cmd} > tmp 18 cat tmp | jq -r .key > $key 19 cat tmp | jq -r .cert > $cert 20 cat tmp | jq -r .csr > $csr 21 22 touch $out 23 ) 2>&1 | fold -w 80 -s 24 ''; 25 in { 26 key = secrets.key; 27 cert = secrets.cert; 28 csr = secrets.csr; 29 }; 30 31 writeCFSSL = content: 32 pkgs.runCommand content.name { 33 buildInputs = [ pkgs.cfssl pkgs.jq ]; 34 } '' 35 mkdir -p $out 36 cd $out 37 38 json=${pkgs.lib.escapeShellArg (builtins.toJSON content)} 39 40 # for a given $field in the $json, treat the associated value as a 41 # file path and substitute the contents thereof into the $json 42 # object. 43 expandFileField() { 44 local field=$1 45 if jq -e --arg field "$field" 'has($field)'; then 46 local path="$(echo "$json" | jq -r ".$field")" 47 json="$(echo "$json" | jq --arg val "$(cat "$path")" ".$field = \$val")" 48 fi 49 } 50 51 expandFileField key 52 expandFileField ca 53 expandFileField cert 54 55 echo "$json" | cfssljson -bare ${content.name} 56 ''; 57 58 noCSR = content: pkgs.lib.filterAttrs (n: v: n != "csr") content; 59 noKey = content: pkgs.lib.filterAttrs (n: v: n != "key") content; 60 61 writeFile = content: 62 if pkgs.lib.isDerivation content 63 then content 64 else pkgs.writeText "content" (builtins.toJSON content); 65 66 createServingCertKey = { ca, cn, hosts? [], size ? 2048, name ? cn }: 67 noCSR ( 68 (runWithCFSSL name "gencert -ca=${writeFile ca.cert} -ca-key=${writeFile ca.key} -profile=server -config=${writeFile ca.config} ${writeFile { 69 CN = cn; 70 hosts = hosts; 71 key = { algo = "rsa"; inherit size; }; 72 }}") // { inherit name; } 73 ); 74 75 createClientCertKey = { ca, cn, groups ? [], size ? 2048, name ? cn }: 76 noCSR ( 77 (runWithCFSSL name "gencert -ca=${writeFile ca.cert} -ca-key=${writeFile ca.key} -profile=client -config=${writeFile ca.config} ${writeFile { 78 CN = cn; 79 names = map (group: {O = group;}) groups; 80 hosts = [""]; 81 key = { algo = "rsa"; inherit size; }; 82 }}") // { inherit name; } 83 ); 84 85 createSigningCertKey = { C ? "xx", ST ? "x", L ? "x", O ? "x", OU ? "x", CN ? "ca", emailAddress ? "x", expiry ? "43800h", size ? 2048, name ? CN }: 86 (noCSR (runWithCFSSL CN "genkey -initca ${writeFile { 87 key = { algo = "rsa"; inherit size; }; 88 names = [{ inherit C ST L O OU CN emailAddress; }]; 89 }}")) // { 90 inherit name; 91 config.signing = { 92 default.expiry = expiry; 93 profiles = { 94 server = { 95 inherit expiry; 96 usages = [ 97 "signing" 98 "key encipherment" 99 "server auth" 100 ]; 101 }; 102 client = { 103 inherit expiry; 104 usages = [ 105 "signing" 106 "key encipherment" 107 "client auth" 108 ]; 109 }; 110 peer = { 111 inherit expiry; 112 usages = [ 113 "signing" 114 "key encipherment" 115 "server auth" 116 "client auth" 117 ]; 118 }; 119 }; 120 }; 121 }; 122 123 ca = createSigningCertKey {}; 124 125 kube-apiserver = createServingCertKey { 126 inherit ca; 127 cn = "kube-apiserver"; 128 hosts = ["kubernetes.default" "kubernetes.default.svc" "localhost" "api.${externalDomain}" serviceClusterIp]; 129 }; 130 131 kubelet = createServingCertKey { 132 inherit ca; 133 cn = "kubelet"; 134 hosts = ["*.${externalDomain}"]; 135 }; 136 137 service-accounts = createServingCertKey { 138 inherit ca; 139 cn = "kube-service-accounts"; 140 }; 141 142 etcd = createServingCertKey { 143 inherit ca; 144 cn = "etcd"; 145 hosts = ["etcd.${externalDomain}"]; 146 }; 147 148 etcd-client = createClientCertKey { 149 inherit ca; 150 cn = "etcd-client"; 151 }; 152 153 kubelet-client = createClientCertKey { 154 inherit ca; 155 cn = "kubelet-client"; 156 groups = ["system:masters"]; 157 }; 158 159 apiserver-client = { 160 kubelet = hostname: createClientCertKey { 161 inherit ca; 162 name = "apiserver-client-kubelet-${hostname}"; 163 cn = "system:node:${hostname}.${externalDomain}"; 164 groups = ["system:nodes"]; 165 }; 166 167 kube-proxy = createClientCertKey { 168 inherit ca; 169 name = "apiserver-client-kube-proxy"; 170 cn = "system:kube-proxy"; 171 groups = ["system:kube-proxy" "system:nodes"]; 172 }; 173 174 kube-controller-manager = createClientCertKey { 175 inherit ca; 176 name = "apiserver-client-kube-controller-manager"; 177 cn = "system:kube-controller-manager"; 178 groups = ["system:masters"]; 179 }; 180 181 kube-scheduler = createClientCertKey { 182 inherit ca; 183 name = "apiserver-client-kube-scheduler"; 184 cn = "system:kube-scheduler"; 185 groups = ["system:kube-scheduler"]; 186 }; 187 188 admin = createClientCertKey { 189 inherit ca; 190 cn = "admin"; 191 groups = ["system:masters"]; 192 }; 193 }; 194in { 195 master = pkgs.buildEnv { 196 name = "master-keys"; 197 paths = [ 198 (writeCFSSL (noKey ca)) 199 (writeCFSSL kube-apiserver) 200 (writeCFSSL kubelet-client) 201 (writeCFSSL apiserver-client.kube-controller-manager) 202 (writeCFSSL apiserver-client.kube-scheduler) 203 (writeCFSSL service-accounts) 204 (writeCFSSL etcd) 205 ]; 206 }; 207 208 worker = pkgs.buildEnv { 209 name = "worker-keys"; 210 paths = [ 211 (writeCFSSL (noKey ca)) 212 (writeCFSSL kubelet) 213 (writeCFSSL apiserver-client.kube-proxy) 214 (writeCFSSL etcd-client) 215 ] ++ map (hostname: writeCFSSL (apiserver-client.kubelet hostname)) kubelets; 216 }; 217 218 admin = writeCFSSL apiserver-client.admin; 219}