Skip to content

Commit 52039c5

Browse files
authored
Merge pull request #205 from renoki-co/feature/cmd-auth
[fix] Added support for cmd-like auth
2 parents 8027fec + 52f1769 commit 52039c5

11 files changed

+121
-18
lines changed

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"illuminate/macroable": "^8.83|^9.0.1",
1717
"illuminate/support": "^8.83|^9.0.1",
1818
"ratchet/pawl": "^0.4.1",
19+
"symfony/process": "^5.4|^6.0",
1920
"vierbergenlars/php-semver": "^2.1|^3.0"
2021
},
2122
"suggest": {

src/Kinds/K8sPod.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ public function getInitContainerStatuses(bool $asInstance = true): array
399399
*
400400
* @param string $containerName
401401
* @param bool $asInstance
402-
* @return array|null
402+
* @return \RenokiCo\PhpK8s\Instances\Container|array|null
403403
*/
404404
public function getContainer(string $containerName, bool $asInstance = true)
405405
{

src/Traits/Cluster/AuthenticatesCluster.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
namespace RenokiCo\PhpK8s\Traits\Cluster;
44

5+
use Illuminate\Support\Arr;
56
use RenokiCo\PhpK8s\Kinds\K8sResource;
7+
use Symfony\Component\Process\Process;
68

79
trait AuthenticatesCluster
810
{
@@ -70,6 +72,37 @@ public function withToken(string $token = null)
7072
return $this;
7173
}
7274

75+
/**
76+
* Load the token from provider command line.
77+
*
78+
* @param string $cmdPath
79+
* @param string|nll $cmdArgs
80+
* @param string|null $tokenPath
81+
* @return $this
82+
*/
83+
public function withTokenFromCommandProvider(string $cmdPath, string $cmdArgs = null, string $tokenPath = null)
84+
{
85+
$process = Process::fromShellCommandline("{$cmdPath} {$cmdArgs}");
86+
87+
$process->run();
88+
89+
if ($process->getErrorOutput()) {
90+
return $this;
91+
}
92+
93+
$output = $process->getOutput();
94+
95+
if (! $tokenPath) {
96+
return $this->withToken(trim($output));
97+
}
98+
99+
$json = json_decode($output, true);
100+
101+
return $this->withToken(
102+
trim(Arr::get($json, str_replace(['{.', '}'], '', $tokenPath)))
103+
);
104+
}
105+
73106
/**
74107
* Load a Bearer Token from file.
75108
*

src/Traits/Cluster/LoadsFromKubeConfig.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,16 @@ protected function loadKubeConfigFromArray(array $kubeconfig, string $context =
218218
$this->withToken($userConfig['user']['auth-provider']['config']['access-token']);
219219
}
220220

221+
if (isset($userConfig['user']['auth-provider']['config']['cmd-path'])) {
222+
$authProviderConfig = $userConfig['user']['auth-provider']['config'];
223+
224+
$this->withTokenFromCommandProvider(
225+
$authProviderConfig['cmd-path'],
226+
$authProviderConfig['cmd-args'] ?? null,
227+
$authProviderConfig['token-key'] ?? null,
228+
);
229+
}
230+
221231
if (isset($clusterConfig['cluster']['insecure-skip-tls-verify']) && $clusterConfig['cluster']['insecure-skip-tls-verify']) {
222232
$this->withoutSslChecks();
223233
}

src/Traits/Cluster/MakesHttpCalls.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public function getClient()
3838
$options = [
3939
RequestOptions::HEADERS => [
4040
'Content-Type' => 'application/json',
41+
'Accept-Encoding' => 'gzip, deflate',
4142
],
4243
RequestOptions::VERIFY => true,
4344
];

tests/ClusterRoleBindingTest.php

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public function test_cluster_role_binding_build()
1919
->addVerbs(['get', 'list', 'watch']);
2020

2121
$cr = $this->cluster->clusterRole()
22-
->setName('admin-cr')
22+
->setName('admin-cr-for-binding')
2323
->setLabels(['tier' => 'backend'])
2424
->addRules([$rule]);
2525

@@ -39,7 +39,7 @@ public function test_cluster_role_binding_build()
3939
$this->assertEquals('user-binding', $crb->getName());
4040
$this->assertEquals(['tier' => 'backend'], $crb->getLabels());
4141
$this->assertEquals([$subject], $crb->getSubjects());
42-
$this->assertEquals(['apiGroup' => 'rbac.authorization.k8s.io', 'kind' => 'ClusterRole', 'name' => 'admin-cr'], $crb->getRole());
42+
$this->assertEquals(['apiGroup' => 'rbac.authorization.k8s.io', 'kind' => 'ClusterRole', 'name' => 'admin-cr-for-binding'], $crb->getRole());
4343
}
4444

4545
public function test_cluster_role_binding_from_yaml()
@@ -51,7 +51,7 @@ public function test_cluster_role_binding_from_yaml()
5151
->addVerbs(['get', 'list', 'watch']);
5252

5353
$cr = $this->cluster->clusterRole()
54-
->setName('admin-cr')
54+
->setName('admin-cr-for-binding')
5555
->setLabels(['tier' => 'backend'])
5656
->addRules([$rule]);
5757

@@ -66,7 +66,7 @@ public function test_cluster_role_binding_from_yaml()
6666
$this->assertEquals('user-binding', $crb->getName());
6767
$this->assertEquals(['tier' => 'backend'], $crb->getLabels());
6868
$this->assertEquals([$subject], $crb->getSubjects());
69-
$this->assertEquals(['apiGroup' => 'rbac.authorization.k8s.io', 'kind' => 'ClusterRole', 'name' => 'admin-cr'], $crb->getRole());
69+
$this->assertEquals(['apiGroup' => 'rbac.authorization.k8s.io', 'kind' => 'ClusterRole', 'name' => 'admin-cr-for-binding'], $crb->getRole());
7070
}
7171

7272
public function test_cluster_role_binding_api_interaction()
@@ -89,7 +89,7 @@ public function runCreationTests()
8989
->addVerbs(['get', 'list', 'watch']);
9090

9191
$cr = $this->cluster->clusterRole()
92-
->setName('admin-cr')
92+
->setName('admin-cr-for-binding')
9393
->setLabels(['tier' => 'backend'])
9494
->addRules([$rule]);
9595

@@ -120,7 +120,7 @@ public function runCreationTests()
120120
$this->assertEquals('user-binding', $crb->getName());
121121
$this->assertEquals(['tier' => 'backend'], $crb->getLabels());
122122
$this->assertEquals([$subject], $crb->getSubjects());
123-
$this->assertEquals(['apiGroup' => 'rbac.authorization.k8s.io', 'kind' => 'ClusterRole', 'name' => 'admin-cr'], $crb->getRole());
123+
$this->assertEquals(['apiGroup' => 'rbac.authorization.k8s.io', 'kind' => 'ClusterRole', 'name' => 'admin-cr-for-binding'], $crb->getRole());
124124
}
125125

126126
public function runGetAllTests()
@@ -143,7 +143,7 @@ public function runGetTests()
143143
->setKind('User')
144144
->setName('user-1');
145145

146-
$cr = $this->cluster->getClusterRoleByName('admin-cr');
146+
$cr = $this->cluster->getClusterRoleByName('admin-cr-for-binding');
147147
$crb = $this->cluster->getClusterRoleBindingByName('user-binding');
148148

149149
$this->assertInstanceOf(K8sClusterRoleBinding::class, $crb);
@@ -154,12 +154,12 @@ public function runGetTests()
154154
$this->assertEquals('user-binding', $crb->getName());
155155
$this->assertEquals(['tier' => 'backend'], $crb->getLabels());
156156
$this->assertEquals([$subject], $crb->getSubjects());
157-
$this->assertEquals(['apiGroup' => 'rbac.authorization.k8s.io', 'kind' => 'ClusterRole', 'name' => 'admin-cr'], $crb->getRole());
157+
$this->assertEquals(['apiGroup' => 'rbac.authorization.k8s.io', 'kind' => 'ClusterRole', 'name' => 'admin-cr-for-binding'], $crb->getRole());
158158
}
159159

160160
public function runUpdateTests()
161161
{
162-
$cr = $this->cluster->getClusterRoleByName('admin-cr');
162+
$cr = $this->cluster->getClusterRoleByName('admin-cr-for-binding');
163163
$crb = $this->cluster->getClusterRoleBindingByName('user-binding');
164164

165165
$subject = K8s::subject()
@@ -179,12 +179,12 @@ public function runUpdateTests()
179179
$this->assertEquals('user-binding', $crb->getName());
180180
$this->assertEquals(['tier' => 'backend'], $crb->getLabels());
181181
$this->assertEquals([$subject], $crb->getSubjects());
182-
$this->assertEquals(['apiGroup' => 'rbac.authorization.k8s.io', 'kind' => 'ClusterRole', 'name' => 'admin-cr'], $crb->getRole());
182+
$this->assertEquals(['apiGroup' => 'rbac.authorization.k8s.io', 'kind' => 'ClusterRole', 'name' => 'admin-cr-for-binding'], $crb->getRole());
183183
}
184184

185185
public function runDeletionTests()
186186
{
187-
$cr = $this->cluster->getClusterRoleByName('admin-cr');
187+
$cr = $this->cluster->getClusterRoleByName('admin-cr-for-binding');
188188
$crb = $this->cluster->getClusterRoleBindingByName('user-binding');
189189

190190
$this->assertTrue($cr->delete());
@@ -200,7 +200,7 @@ public function runDeletionTests()
200200

201201
$this->expectException(KubernetesAPIException::class);
202202

203-
$this->cluster->getClusterRoleByName('admin-cr');
203+
$this->cluster->getClusterRoleByName('admin-cr-for-binding');
204204
$this->cluster->getClusterRoleBindingByName('user-binding');
205205
}
206206

tests/KubeConfigTest.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,4 +241,22 @@ public function test_kube_config_from_array_with_base64_encoded_ssl()
241241
$this->assertEquals("some-cert\n", file_get_contents($certPath));
242242
$this->assertEquals("some-key\n", file_get_contents($keyPath));
243243
}
244+
245+
public function test_kube_config_from_yaml_file_with_cmd_auth_as_json()
246+
{
247+
$cluster = KubernetesCluster::fromKubeConfigYamlFile(__DIR__.'/cluster/kubeconfig-command.yaml', 'minikube');
248+
249+
['headers' => ['authorization' => $token]] = $cluster->getClient()->getConfig();
250+
251+
$this->assertEquals('Bearer some-token', $token);
252+
}
253+
254+
public function test_kube_config_from_yaml_file_with_cmd_auth_as_string()
255+
{
256+
$cluster = KubernetesCluster::fromKubeConfigYamlFile(__DIR__.'/cluster/kubeconfig-command.yaml', 'minikube-2');
257+
258+
['headers' => ['authorization' => $token]] = $cluster->getClient()->getConfig();
259+
260+
$this->assertEquals('Bearer some-token', $token);
261+
}
244262
}

tests/PodTest.php

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ public function test_pod_api_interaction()
111111
public function test_pod_exec()
112112
{
113113
$busybox = K8s::container()
114-
->setName('busybox')
114+
->setName('busybox-exec')
115115
->setImage('busybox')
116116
->setCommand(['/bin/sh', '-c', 'sleep 7200']);
117117

@@ -126,7 +126,7 @@ public function test_pod_exec()
126126
$pod->refresh();
127127
}
128128

129-
$messages = $pod->exec(['/bin/sh', '-c', 'echo 1 && echo 2 && echo 3'], 'busybox');
129+
$messages = $pod->exec(['/bin/sh', '-c', 'echo 1 && echo 2 && echo 3'], 'busybox-exec');
130130

131131
$hasDesiredOutput = collect($messages)->where('channel', 'stdout')->filter(function ($message) {
132132
return Str::contains($message['output'], '1')
@@ -142,15 +142,15 @@ public function test_pod_exec()
142142
public function test_pod_attach()
143143
{
144144
$mysql = K8s::container()
145-
->setName('mysql')
145+
->setName('mysql-attach')
146146
->setImage('mysql', '5.7')
147147
->setPorts([
148148
['name' => 'mysql', 'protocol' => 'TCP', 'containerPort' => 3306],
149149
])
150150
->setEnv(['MYSQL_ROOT_PASSWORD' => 'test']);
151151

152152
$pod = $this->cluster->pod()
153-
->setName('mysql-exec')
153+
->setName('mysql-attach')
154154
->setContainers([$mysql])
155155
->createOrUpdate();
156156

tests/cluster/kubeconfig-command.yaml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
apiVersion: v1
2+
clusters:
3+
- cluster:
4+
certificate-authority-data: c29tZS1jYQo= # "some-ca"
5+
server: https://minikube:8443
6+
name: minikube
7+
- cluster:
8+
certificate-authority-data: c29tZS1jYQo= # "some-ca"
9+
server: https://minikube:8443
10+
name: minikube-2
11+
contexts:
12+
- context:
13+
cluster: minikube
14+
user: minikube
15+
name: minikube
16+
- context:
17+
cluster: minikube-2
18+
user: minikube-2
19+
name: minikube-2
20+
current-context: minikube
21+
kind: Config
22+
preferences: {}
23+
users:
24+
- name: minikube
25+
user:
26+
auth-provider:
27+
config:
28+
cmd-args: ''
29+
cmd-path: cat tests/cluster/token.json
30+
token-key: '{.nested.token}'
31+
- name: minikube-2
32+
user:
33+
auth-provider:
34+
config:
35+
cmd-path: 'echo some-token'

tests/cluster/token.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"nested": {
3+
"token": "some-token"
4+
}
5+
}

tests/yaml/clusterrolebinding.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ metadata:
77
roleRef:
88
apiGroup: rbac.authorization.k8s.io
99
kind: ClusterRole
10-
name: admin-cr
10+
name: admin-cr-for-binding
1111
subjects:
1212
- apiGroup: rbac.authorization.k8s.io
1313
kind: User

0 commit comments

Comments
 (0)