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

Fix #5608 Support authentication with certificate in exec-credentials #5612

Merged
merged 10 commits into from
Nov 29, 2023
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#### Dependency Upgrade

#### New Features
* Fix #5608 Support authentication with certificate in exec-credentials

#### _**Note**_: Breaking changes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -785,10 +785,16 @@ private static void mergeKubeConfigExecCredential(Config config, ExecConfig exec
if (exec != null) {
try {
ExecCredential ec = getExecCredentialFromExecConfig(exec, configFile);
if (ec != null && ec.status != null && ec.status.token != null) {
config.setAutoOAuthToken(ec.status.token);
} else {
LOGGER.warn("No token returned");
if (ec != null && ec.status != null) {
if (ec.status.token != null) {
config.setAutoOAuthToken(ec.status.token);
} else if (Utils.isNotNullOrEmpty(ec.status.clientCertificateData)
&& Utils.isNotNullOrEmpty(ec.status.clientKeyData)) {
config.setClientCertData(ec.status.clientCertificateData);
config.setClientKeyData(ec.status.clientKeyData);
} else {
LOGGER.warn("No token or certificate returned");
}
}
} catch (InterruptedException interruptedException) {
Thread.currentThread().interrupt();
Expand Down Expand Up @@ -898,7 +904,9 @@ public static final class ExecCredentialSpec {
@JsonIgnoreProperties(ignoreUnknown = true)
public static final class ExecCredentialStatus {
public String token;
// TODO clientCertificateData, clientKeyData, expirationTimestamp
public String clientCertificateData;
public String clientKeyData;
// TODO expirationTimestamp
}

private static boolean tryNamespaceFromPath(Config config) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,16 @@ class ConfigTest {
private static final String TEST_KUBECONFIG_NO_CURRENT_CONTEXT_FILE = Utils
.filePath(ConfigTest.class.getResource("/test-kubeconfig-nocurrentctxt.yml"));

private static final String TEST_KUBECONFIG_EXEC_FILE_CERT_AUTH = Utils
.filePath(ConfigTest.class.getResource("/test-kubeconfig-exec-cert-auth"));
private static final String TEST_KUBECONFIG_EXEC_WIN_FILE_CERT_AUTH = Utils
.filePath(ConfigTest.class.getResource("/test-kubeconfig-exec-win-cert-auth"));
private static final String TEST_KUBECONFIG_EXEC_FILE_CERT_AUTH_EC_INVALID = Utils
.filePath(ConfigTest.class.getResource("/test-kubeconfig-exec-cert-auth-ec-invalid"));
private static final String TEST_KUBECONFIG_EXEC_WIN_FILE_CERT_AUTH_EC_INVALID = Utils
.filePath(ConfigTest.class.getResource("/test-kubeconfig-exec-win-cert-auth-ec-invalid"));
private static final String TEST_CERT_GENERATOR_FILE = Utils.filePath(ConfigTest.class.getResource("/cert-generator"));

@BeforeEach
public void setUp() {
System.getProperties().remove(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY);
Expand Down Expand Up @@ -504,6 +514,44 @@ void should_accept_client_authentication_commands_with_null_args() throws Except
}
}

@Test
void testClientAuthenticationWithCert() throws Exception {
try {
if (FileSystem.getCurrent() == FileSystem.WINDOWS) {
System.setProperty(Config.KUBERNETES_KUBECONFIG_FILE, TEST_KUBECONFIG_EXEC_WIN_FILE_CERT_AUTH);
} else {
Files.setPosixFilePermissions(Paths.get(TEST_CERT_GENERATOR_FILE), PosixFilePermissions.fromString("rwxrwxr-x"));
System.setProperty(Config.KUBERNETES_KUBECONFIG_FILE, TEST_KUBECONFIG_EXEC_FILE_CERT_AUTH);
}

Config config = Config.autoConfigure(null);
assertNotNull(config);
assertEquals("CERT DATA", config.getClientCertData());
assertEquals("KEY DATA", config.getClientKeyData());
} finally {
System.clearProperty(Config.KUBERNETES_KUBECONFIG_FILE);
}
}

@Test
void testClientAuthenticationWithCertAndECInvalid() throws Exception {
try {
if (FileSystem.getCurrent() == FileSystem.WINDOWS) {
System.setProperty(Config.KUBERNETES_KUBECONFIG_FILE, TEST_KUBECONFIG_EXEC_WIN_FILE_CERT_AUTH_EC_INVALID);
} else {
Files.setPosixFilePermissions(Paths.get(TEST_CERT_GENERATOR_FILE), PosixFilePermissions.fromString("rwxrwxr-x"));
System.setProperty(Config.KUBERNETES_KUBECONFIG_FILE, TEST_KUBECONFIG_EXEC_FILE_CERT_AUTH_EC_INVALID);
}

Config config = Config.autoConfigure(null);
assertNotNull(config);
assertNull(config.getClientCertData());
assertNull(config.getClientKeyData());
} finally {
System.clearProperty(Config.KUBERNETES_KUBECONFIG_FILE);
}
}

@Test
void should_accept_client_authentication_commands_args_with_spaces() throws Exception {
try {
Expand Down
14 changes: 14 additions & 0 deletions kubernetes-client-api/src/test/resources/cert-generator
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/sh
certData=`echo $PART1 $1 | tr '[a-z]' '[A-Z]'`
keyData=`echo $PART2 $1 | tr '[a-z]' '[A-Z]'`
cat <<EOF
{
"kind": "ExecCredential",
"apiVersion": "client.authentication.k8s.io/v1",
"spec": {},
"status": {
"clientCertificateData": "$certData",
"clientKeyData": "$keyData"
}
}
EOF
48 changes: 48 additions & 0 deletions kubernetes-client-api/src/test/resources/cert-generator-win.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
@REM
@REM Copyright (C) 2015 Red Hat, Inc.
@REM
@REM Licensed under the Apache License, Version 2.0 (the "License");
@REM you may not use this file except in compliance with the License.
@REM You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing, software
@REM distributed under the License is distributed on an "AS IS" BASIS,
@REM WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@REM See the License for the specific language governing permissions and
@REM limitations under the License.
@REM

@echo off
SET valid=true
IF [%PART1%]==[] (
IF [%PART2%]==[] (
SET valid=false
)
)
IF [%valid%]==[true] (
IF [%1]==[] (
SET certData=%PART1%
SET keyData=%PART2%
) ELSE (
SET certData=%PART1% %~1
SET keyData=%PART2% %~1
)
CALL :upper certData
CALL :upper keyData
)

echo {
echo "kind": "ExecCredential",
echo "apiVersion": "client.authentication.k8s.io/v1",
echo "spec": {},
echo "status": {
echo "clientCertificateData": "%certData%",
echo "clientKeyData": "%keyData%"
echo }
echo }
GOTO :EOF

:upper
FOR %%a IN (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) DO CALL SET "%1=%%%1:%%a=%%a%%%"
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
apiVersion: v1
kind: Config
clusters:
- cluster:
server: https://wherever
name: test
contexts:
- context:
cluster: test
user: test
name: test
current-context: test
users:
- name: test
user:
exec:
apiVersion: client.authentication.k8s.io/v1
args:
- data
command: ./cert-generator
env:
- name: PART1
value: cert
- name: PART2
value: key
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
apiVersion: v1
kind: Config
clusters:
- cluster:
server: https://wherever
name: test
contexts:
- context:
cluster: test
user: test
name: test
current-context: test
users:
- name: test
user:
exec:
apiVersion: client.authentication.k8s.io/v1
args: null
command: ./cert-generator
env: null
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
apiVersion: v1
kind: Config
clusters:
- cluster:
server: https://wherever
name: test
contexts:
- context:
cluster: test
user: test
name: test
current-context: test
users:
- name: test
user:
exec:
apiVersion: client.authentication.k8s.io/v1
args:
- data
command: ".\\cert-generator-win.bat"
env:
- name: PART1
value: cert
- name: PART2
value: key
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
apiVersion: v1
kind: Config
clusters:
- cluster:
server: https://wherever
name: test
contexts:
- context:
cluster: test
user: test
name: test
current-context: test
users:
- name: test
user:
exec:
apiVersion: client.authentication.k8s.io/v1
args: null
command: ".\\cert-generator-win.bat"
env: null
Loading