1{ system ? builtins.currentSystem, pkgs ? import <nixpkgs> { inherit system; } }:
2with import ./base.nix { inherit system; };
3let
4
5 roServiceAccount = pkgs.writeText "ro-service-account.json" (builtins.toJSON {
6 kind = "ServiceAccount";
7 apiVersion = "v1";
8 metadata = {
9 name = "read-only";
10 namespace = "default";
11 };
12 });
13
14 roRoleBinding = pkgs.writeText "ro-role-binding.json" (builtins.toJSON {
15 apiVersion = "rbac.authorization.k8s.io/v1";
16 kind = "RoleBinding";
17 metadata = {
18 name = "read-pods";
19 namespace = "default";
20 };
21 roleRef = {
22 apiGroup = "rbac.authorization.k8s.io";
23 kind = "Role";
24 name = "pod-reader";
25 };
26 subjects = [{
27 kind = "ServiceAccount";
28 name = "read-only";
29 namespace = "default";
30 }];
31 });
32
33 roRole = pkgs.writeText "ro-role.json" (builtins.toJSON {
34 apiVersion = "rbac.authorization.k8s.io/v1";
35 kind = "Role";
36 metadata = {
37 name = "pod-reader";
38 namespace = "default";
39 };
40 rules = [{
41 apiGroups = [""];
42 resources = ["pods"];
43 verbs = ["get" "list" "watch"];
44 }];
45 });
46
47 kubectlPod = pkgs.writeText "kubectl-pod.json" (builtins.toJSON {
48 kind = "Pod";
49 apiVersion = "v1";
50 metadata.name = "kubectl";
51 metadata.namespace = "default";
52 metadata.labels.name = "kubectl";
53 spec.serviceAccountName = "read-only";
54 spec.containers = [{
55 name = "kubectl";
56 image = "kubectl:latest";
57 command = ["/bin/tail" "-f"];
58 imagePullPolicy = "Never";
59 tty = true;
60 }];
61 });
62
63 kubectlPod2 = pkgs.writeTextDir "kubectl-pod-2.json" (builtins.toJSON {
64 kind = "Pod";
65 apiVersion = "v1";
66 metadata.name = "kubectl-2";
67 metadata.namespace = "default";
68 metadata.labels.name = "kubectl-2";
69 spec.serviceAccountName = "read-only";
70 spec.containers = [{
71 name = "kubectl-2";
72 image = "kubectl:latest";
73 command = ["/bin/tail" "-f"];
74 imagePullPolicy = "Never";
75 tty = true;
76 }];
77 });
78
79 kubectl = pkgs.runCommand "copy-kubectl" { buildInputs = [ pkgs.kubernetes ]; } ''
80 mkdir -p $out/bin
81 cp ${pkgs.kubernetes}/bin/kubectl $out/bin/kubectl
82 '';
83
84 kubectlImage = pkgs.dockerTools.buildImage {
85 name = "kubectl";
86 tag = "latest";
87 contents = [ kubectl pkgs.busybox kubectlPod2 ];
88 config.Entrypoint = ["/bin/sh"];
89 };
90
91 base = {
92 name = "rbac";
93 };
94
95 singlenode = base // {
96 test = ''
97 machine1.wait_until_succeeds("kubectl get node machine1.my.zyx | grep -w Ready")
98
99 machine1.wait_until_succeeds(
100 "${pkgs.gzip}/bin/zcat ${kubectlImage} | ${pkgs.containerd}/bin/ctr -n k8s.io image import -"
101 )
102
103 machine1.wait_until_succeeds(
104 "kubectl apply -f ${roServiceAccount}"
105 )
106 machine1.wait_until_succeeds(
107 "kubectl apply -f ${roRole}"
108 )
109 machine1.wait_until_succeeds(
110 "kubectl apply -f ${roRoleBinding}"
111 )
112 machine1.wait_until_succeeds(
113 "kubectl create -f ${kubectlPod}"
114 )
115
116 machine1.wait_until_succeeds("kubectl get pod kubectl | grep Running")
117
118 machine1.wait_until_succeeds("kubectl exec -ti kubectl -- kubectl get pods")
119 machine1.fail("kubectl exec -ti kubectl -- kubectl create -f /kubectl-pod-2.json")
120 machine1.fail("kubectl exec -ti kubectl -- kubectl delete pods -l name=kubectl")
121 '';
122 };
123
124 multinode = base // {
125 test = ''
126 # Node token exchange
127 machine1.wait_until_succeeds(
128 "cp -f /var/lib/cfssl/apitoken.secret /tmp/shared/apitoken.secret"
129 )
130 machine2.wait_until_succeeds(
131 "cat /tmp/shared/apitoken.secret | nixos-kubernetes-node-join"
132 )
133
134 machine1.wait_until_succeeds("kubectl get node machine2.my.zyx | grep -w Ready")
135
136 machine2.wait_until_succeeds(
137 "${pkgs.gzip}/bin/zcat ${kubectlImage} | ${pkgs.containerd}/bin/ctr -n k8s.io image import -"
138 )
139
140 machine1.wait_until_succeeds(
141 "kubectl apply -f ${roServiceAccount}"
142 )
143 machine1.wait_until_succeeds(
144 "kubectl apply -f ${roRole}"
145 )
146 machine1.wait_until_succeeds(
147 "kubectl apply -f ${roRoleBinding}"
148 )
149 machine1.wait_until_succeeds(
150 "kubectl create -f ${kubectlPod}"
151 )
152
153 machine1.wait_until_succeeds("kubectl get pod kubectl | grep Running")
154
155 machine1.wait_until_succeeds("kubectl exec -ti kubectl -- kubectl get pods")
156 machine1.fail("kubectl exec -ti kubectl -- kubectl create -f /kubectl-pod-2.json")
157 machine1.fail("kubectl exec -ti kubectl -- kubectl delete pods -l name=kubectl")
158 '';
159 };
160
161in {
162 singlenode = mkKubernetesSingleNodeTest singlenode;
163 multinode = mkKubernetesMultiNodeTest multinode;
164}