One more thing is that it is impossible to view the secret after i created the service connection, may i know if there are any method to view it so that i can know the mistake the api made?
Create K8S Service Connection of Service Account Auth Type in Node JS failed
Issue: Azure DevOps REST API cannot create Kubernetes service connections for a private cluster with Token-scheme authentication that work with kubectl tasks, even when using the exact same payload structure as the UI.
Impact: Infrastructure-as-code automation for creating Kubernetes service connections is broken. Only manual UI creation works.
Problem Description
When creating a Kubernetes (AKS) service connection for a private cluster in Azure DevOps using the REST API with Token-scheme authentication and service account credentials, the connection is created successfully and appears in the UI correctly. However, when attempting to use this connection with the kubectl task in a pipeline, the task fails with deserialization errors.
Identical connections created manually via the Azure DevOps UI work perfectly with kubectl tasks.
Reproduction Steps
1. Capture UI Request
Using browser developer tools, capture the exact HTTP request the Azure DevOps UI sends when creating a Kubernetes service connection:
POST /GTI-Lab-Luis/_apis/serviceendpoint/endpoints?api-version=6.0-preview.4
Host: dev.azure.com
Authorization: Bearer <token>
Content-Type: application/json
Accept: application/json;api-version=6.0-preview.4
{
"authorization": {
"parameters": {
"serviceAccountCertificate": "LS0tLS1CRUdJTi...", // BASE64
"isCreatedFromSecretYaml": "true",
"apitoken": "ZXlKaGJHY2lPaUpTVXpJ..." // BASE64
},
"scheme": "Token"
},
"data": {
"authorizationType": "ServiceAccount"
},
"name": "aks-test-connection",
"type": "kubernetes",
"url": "https://your-cluster.azmk8s.io:443",
"description": "Test AKS connection",
"serviceEndpointProjectReferences": [
{
"projectReference": {
"id": "your-project-id",
"name": "Your-Project"
},
"name": "aks-test-connection"
}
]
}
UI Result: ✅ Connection created, ✅ Works with kubectl task
2. Replicate via Node.js Script
#!/usr/bin/env node
const CONFIG = {
organization: 'your-org',
project: 'Your-Project',
projectId: 'your-project-id',
connectionName: 'aks-test-connection-api',
serverUrl: 'https://your-cluster.azmk8s.io:443',
tokenBase64: 'ZXlKaGJHY2lPaUpTVXpJ...', // Your service account token (base64)
caCertBase64: 'LS0tLS1CRUdJTi...', // Your CA certificate (base64)
pat: 'your-pat-token' // Personal Access Token
};
async function apiCall(method, url, body = null) {
const auth = Buffer.from(`:${CONFIG.pat}`).toString('base64');
const options = {
method,
headers: {
'Authorization': `Basic ${auth}`,
'Content-Type': 'application/json',
'Accept': 'application/json;api-version=6.0-preview.4'
}
};
if (body) {
options.body = JSON.stringify(body);
}
const response = await fetch(url, options);
if (!response.ok) {
const errorData = await response.text();
throw new Error(`${method} ${url.split('?')[0]}: ${response.status} - ${errorData}`);
}
return response.json();
}
async function main() {
try {
console.log('Creating AKS service connection via API...\n');
// Use ORGANIZATION-LEVEL endpoint with API v6.0 (matching UI)
const createPayload = {
name: CONFIG.connectionName,
type: 'kubernetes',
url: CONFIG.serverUrl,
description: 'AKS connection created via API',
authorization: {
scheme: 'Token',
parameters: {
serviceAccountCertificate: CONFIG.caCertBase64, // BASE64
isCreatedFromSecretYaml: 'true',
apitoken: CONFIG.tokenBase64 // BASE64
}
},
data: {
authorizationType: 'ServiceAccount'
},
serviceEndpointProjectReferences: [
{
projectReference: {
id: CONFIG.projectId,
name: CONFIG.project
},
name: CONFIG.connectionName
}
],
isShared: false,
isReady: true
};
// Organization-level endpoint (matching UI)
const createUrl = `https://dev.azure.com/${CONFIG.organization}/_apis/serviceendpoint/endpoints?api-version=6.0-preview.4`;
const result = await apiCall('POST', createUrl, createPayload);
const connectionId = result.id;
console.log(`✅ Connection created: ${connectionId}`);
console.log(`📋 Name: ${result.name}`);
console.log(`📋 Type: ${result.type}`);
console.log(`📋 Scheme: ${result.authorization.scheme}`);
console.log(`\nNow try using this connection in a kubectl task...\n`);
} catch (error) {
console.error('❌ Error:', error.message);
process.exit(1);
}
}
main();
API Result: ✅ Connection created, ❌ **Fails with kubectl task
**
Error Messages Observed
When using the API-created connection with kubectl task:
Error 1 (Project-level endpoint, v7.1, decoded credentials)
error: error loading config file "/home/azureuser/.../config": yaml: control characters are not allowed
Error 2 (Project-level endpoint, v7.1, base64 credentials)
error: error loading config file "/home/azureuser/.../config": x509: malformed extension OID
Error 3 (Project-level endpoint, v7.1, mixed formats)
error: error loading config file "/home/azureuser/.../config": illegal base64 data at input byte 0
Error 4 (Organization-level endpoint, v6.0, base64 credentials) - Closest to UI
error: error loading config file "/home/azureuser/.../config": illegal base64 data at input byte 142
3. Replicate via curl
#!/bin/bash
# Create AKS Service Connection via Curl
# Tests if curl (raw HTTP) has the same issue as Node.js
ORG="..."
PROJECT="..."
PROJECT_ID="..."
PAT="..."
# Base64 credentials (same as Node.js tests)
CERT_B64="LS0tLS1CRU..."
TOKEN_B64="ZXlKaGJ..."
echo "🔍 Testing with CURL (Raw HTTP)"
echo "========================================"
echo ""
echo "Endpoint: Organization-level (/org/...)"
echo "API Version: 6.0-preview.4"
echo "Auth: Basic Auth with PAT"
echo ""
# Create Basic auth header
AUTH_HEADER=$(echo -n ":$PAT" | base64)
# Create the JSON payload
PAYLOAD=$(cat <<'EOF'
{
"authorization": {
"parameters": {
"serviceAccountCertificate": "LS0tLS1CRU...",
"isCreatedFromSecretYaml": "true",
"apitoken": "ZXlKaGJ..."
},
"scheme": "Token"
},
"data": {
"authorizationType": "ServiceAccount"
},
"name": "aks-curl-test",
"type": "kubernetes",
"url": "https://dns-lasting-snipe-lsauvxoe.privatelink.eastasia.azmk8s.io:443",
"description": "Test using curl",
"serviceEndpointProjectReferences": [
{
"projectReference": {
"id": "6c51d027-7180-4152-9883-7d3db9951281",
"name": "Test-Project"
},
"name": "aks-curl-test"
}
]
}
EOF
)
echo " Running curl command..."
echo ""
# Make the curl request
curl -X POST \
"https://dev.azure.com/$ORG/_apis/serviceendpoint/endpoints?api-version=6.0-preview.4" \
-H "Authorization: Basic $AUTH_HEADER" \
-H "Content-Type: application/json" \
-H "Accept: application/json;api-version=6.0-preview.4" \
-d "$PAYLOAD" \
-s | jq '.' 2>/dev/null || echo "Response (raw):" && curl -X POST \
"https://dev.azure.com/$ORG/_apis/serviceendpoint/endpoints?api-version=6.0-preview.4" \
-H "Authorization: Basic $AUTH_HEADER" \
-H "Content-Type: application/json" \
-H "Accept: application/json;api-version=6.0-preview.4" \
-d "$PAYLOAD"
echo ""
echo "Test complete!"
This time , the error is
Could not fetch Kubectl version. Please make sure that the Kubernetes server is up and running.
/usr/local/bin/kubectl get namespaces -o json
error: unable to load root certificates: unable to parse bytes as PEM block