Skip to content

Commit dcf027a

Browse files
committed
Doc changes for KEP-4412 in azure
1 parent 41af3b4 commit dcf027a

File tree

1 file changed

+204
-8
lines changed

1 file changed

+204
-8
lines changed

AZURE.md

Lines changed: 204 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,21 @@ helm version
7575

7676
## 🚀 Setup Process
7777

78-
The setup process consists of four main steps:
78+
There are **two authentication methods** available for the credential provider:
79+
80+
- **Option A: Nodepool Managed Identity** (Steps 1 → 2 → 3A → 4) — Uses the AKS nodepool's user-assigned managed identity to authenticate via Azure IMDS.
81+
> **Choose this when:** You want a straightforward setup, all nodes in the pool can share the same identity, and you don't need per-workload credential isolation.
82+
83+
- **Option B: Workload Identity** (Steps 1 → 2 → 3B → 4) — Uses Kubernetes projected service account tokens. Provides better security isolation as each service account can have its own identity.
84+
> **Choose this when:** You need fine-grained, per-service-account access control, want to follow the zero-trust principle, or your organization requires workload-level identity isolation.
85+
86+
The setup process consists of the following steps:
7987

8088
1. **Azure AD App Registration** - Create an enterprise application in Azure AD
81-
2. **Federated Identity Credentials** - Configure AKS nodepool access to the Azure App
82-
3. **JFrog Artifactory OIDC Configuration** - Configure Artifactory to create Azure OIDC mappings
89+
2. **Federated Identity Credentials** - Configure AKS nodepool access to the Azure App
90+
3. **JFrog Artifactory OIDC Configuration** - Choose one of:
91+
- **Step 3A:** Configure using Nodepool Managed Identity
92+
- **Step 3B:** Configure using Workload Identity (Projected Service Account Tokens)
8393
4. **Deploy Credentials Provider** - Deploy the credential provider using Helm
8494

8595
---
@@ -329,7 +339,7 @@ You should see your federated credential with:
329339

330340
---
331341

332-
## Step 3: 🐸 JFrog Artifactory OIDC Configuration
342+
## Step 3A: 🐸 JFrog Artifactory OIDC Configuration
333343

334344
Configure JFrog Artifactory to accept OIDC tokens from Azure. This involves creating an OIDC provider and an identity mapping in Artifactory.
335345

@@ -420,13 +430,135 @@ curl -X GET "https://$ARTIFACTORY_URL/access/api/v1/oidc/$OIDC_PROVIDER_NAME" \
420430

421431
---
422432

433+
## Step 3B: Using Projected Service Account Tokens (Workload Identity)
434+
435+
Instead of using the Nodepool's Managed Identity, you can use **Kubernetes Workload Identity**. This allows the Credential Provider to use a specific Kubernetes Service Account to authenticate with Artifactory. This method provides better security isolation as each service account can have its own Azure AD app registration.
436+
437+
**Flow Overview:**
438+
439+
1. The credential provider requests a service account token from Kubernetes with the AKS OIDC issuer audience
440+
441+
2. The provider exchanges the service account token for an OIDC access token from Azure AD using federated credentials
442+
443+
3. The provider exchanges the Azure OIDC token with Artifactory, which validates it and returns a short-lived registry access token
444+
445+
4. The kubelet uses the registry token to authenticate and pull the container image
446+
447+
### Step 3B.1: ✅ Enable OIDC Issuer on AKS
448+
449+
First, ensure your cluster has the OIDC issuer enabled to support Workload Identity:
450+
451+
```bash
452+
# Set variables
453+
RESOURCE_GROUP="your-resource-group"
454+
CLUSTER_NAME="your-aks-cluster"
455+
456+
# Enable OIDC Issuer
457+
az aks update \
458+
--resource-group "$RESOURCE_GROUP" \
459+
--name "$CLUSTER_NAME" \
460+
--enable-oidc-issuer
461+
462+
# Retrieve the OIDC Issuer URL (Save this for Artifactory config)
463+
SERVICE_ACCOUNT_ISSUER=$(az aks show \
464+
--resource-group "$RESOURCE_GROUP" \
465+
--name "$CLUSTER_NAME" \
466+
--query "oidcIssuerProfile.issuerUrl" \
467+
-o tsv)
468+
469+
echo "Service Account Issuer: $SERVICE_ACCOUNT_ISSUER"
470+
```
471+
472+
> **💾 Important:** Save the `SERVICE_ACCOUNT_ISSUER` URL - you'll need it for Artifactory OIDC configuration.
473+
474+
### Step 3B.2: 👤 Configure the Kubernetes Service Account
475+
476+
Create a Service Account that the Credential Provider will use to project the tokens:
477+
478+
```bash
479+
# Set variables
480+
NAMESPACE="jfrog"
481+
SERVICE_ACCOUNT_NAME="jfrog-provider-sa"
482+
483+
# Create the namespace if it doesn't exist
484+
kubectl create namespace "$NAMESPACE" --dry-run=client -o yaml | kubectl apply -f -
485+
486+
# Create the service account
487+
kubectl create serviceaccount "$SERVICE_ACCOUNT_NAME" -n "$NAMESPACE" --dry-run=client -o yaml | kubectl apply -f -
488+
489+
# Annotate the service account with your Azure App Client ID and Workload Identity marker
490+
kubectl annotate serviceaccount "$SERVICE_ACCOUNT_NAME" \
491+
-n "$NAMESPACE" \
492+
azure.workload.identity/client-id="$APP_CLIENT_ID" \
493+
JFrogExchange="true" \
494+
--overwrite
495+
```
496+
497+
> **ℹ️ Note:** The `JFrogExchange="true"` annotation tells the credential provider to use the projected service account token instead of the nodepool's managed identity.
498+
499+
### Step 3B.3: 🐸 Update JFrog Artifactory OIDC Configuration
500+
501+
You must point Artifactory to your AKS Cluster's OIDC Issuer instead of the global Azure Login URL for this flow:
502+
503+
#### Update/Create OIDC Provider in Artifactory:
504+
505+
```bash
506+
# Create or update the OIDC provider
507+
curl -X POST "https://$ARTIFACTORY_URL/access/api/v1/oidc" \
508+
-H "Content-Type: application/json" \
509+
-H "Authorization: Bearer $ARTIFACTORY_ADMIN_TOKEN" \
510+
-d "{
511+
\"name\": \"aks-workload-identity\",
512+
\"issuer_url\": \"$SERVICE_ACCOUNT_ISSUER\",
513+
\"provider_type\": \"Azure\",
514+
\"token_issuer\": \"$SERVICE_ACCOUNT_ISSUER\",
515+
\"use_default_proxy\": false,
516+
\"description\": \"OIDC provider for Azure AKS Workload Identity\"
517+
}"
518+
```
519+
520+
#### Create Identity Mapping for Service Account:
521+
522+
The `sub` (subject) claim must specifically target your Kubernetes Service Account:
523+
524+
```bash
525+
curl -X POST "https://$ARTIFACTORY_URL/access/api/v1/oidc/aks-workload-identity/identity_mappings" \
526+
-H "Content-Type: application/json" \
527+
-H "Authorization: Bearer $ARTIFACTORY_ADMIN_TOKEN" \
528+
-d "{
529+
\"name\": \"aks-workload-identity-mapping\",
530+
\"description\": \"Azure AKS Workload Identity mapping\",
531+
\"claims\": {
532+
\"aud\": \"api://AzureADTokenExchange\",
533+
\"iss\": \"$SERVICE_ACCOUNT_ISSUER\",
534+
\"sub\": \"system:serviceaccount:${NAMESPACE}:${SERVICE_ACCOUNT_NAME}\"
535+
},
536+
\"token_spec\": {
537+
\"username\": \"$ARTIFACTORY_USER\",
538+
\"scope\": \"applied-permissions/user\",
539+
\"audience\": \"*@*\",
540+
\"expires_in\": 3600
541+
},
542+
\"priority\": 1
543+
}"
544+
```
545+
546+
> **⚠️ Important:** The `sub` claim must exactly match the Kubernetes service account format: `system:serviceaccount:<namespace>:<service-account-name>`
547+
548+
---
549+
423550
## Step 4: 🚀 Deploy Credentials Provider
424551

425552
Deploy the credential provider using Helm. For manual deployment with Kubernetes manifests, refer to the [Kubernetes Kubelet Credential Provider documentation](https://kubernetes.io/docs/tasks/administer-cluster/kubelet-credential-provider/).
426553

427554
### 📝 Prepare Values File
428555

429-
Create or update the values file at `./examples/azure-values.yaml` with your configuration values.
556+
Example values files are provided for each authentication method:
557+
558+
- [`./examples/azure-values.yaml`](./examples/azure-values.yaml) — Values file for the Nodepool Managed Identity approach (Option A).
559+
- [`./examples/azure-projected-sa-values.yaml`](./examples/azure-projected-sa-values.yaml) — Values file for the Workload Identity approach using projected service account tokens (Option B).
560+
561+
Update the relevant file with your configuration values.
430562

431563
You can use the following commands to print the values you need:
432564

@@ -447,6 +579,61 @@ echo "jfrog_oidc_provider_name: $OIDC_PROVIDER_NAME"
447579
| `azure_app_audience` | The OIDC audience | `api://AzureADTokenExchange` |
448580
| `jfrog_oidc_provider_name` | The name of the OIDC provider in Artifactory | `azure-aks-oidc-provider` |
449581
| `artifactory_url` | Your JFrog Artifactory URL | `your-instance.jfrog.io` |
582+
583+
#### Configuration for Traditional Nodepool Identity
584+
585+
Use this configuration if you're using the **nodepool's managed identity** (Steps 1-3A):
586+
587+
```yaml
588+
providerConfig:
589+
- name: jfrog-credentials-provider
590+
artifactoryUrl: "<your-instance-dns>"
591+
matchImages:
592+
- "<registry-pattern>"
593+
defaultCacheDuration: 5m
594+
tokenAttributes:
595+
enabled: false # Set to false for nodepool identity
596+
azure:
597+
enabled: true
598+
azure_tenant_id: "<tenant-id>"
599+
azure_app_client_id: "<app-client-id>"
600+
azure_nodepool_client_id: "<nodepool-client-id>"
601+
azure_app_audience: "<app-audience>"
602+
jfrog_oidc_provider_name: "<oidc-provider-name>"
603+
604+
rbac:
605+
create: true
606+
```
607+
608+
#### Configuration for Workload Identity (Projected Service Account Tokens)
609+
610+
Use this configuration if you're using **Kubernetes Workload Identity** (Steps 3B):
611+
612+
```yaml
613+
providerConfig:
614+
- name: jfrog-credentials-provider
615+
artifactoryUrl: "<your-instance-dns>"
616+
matchImages:
617+
- "<registry-pattern>"
618+
defaultCacheDuration: 5m
619+
tokenAttributes:
620+
enabled: true # Enable projected token support
621+
serviceAccountTokenAudience: "<app-audience>"
622+
azure:
623+
enabled: true
624+
azure_app_client_id: "<app-client-id>"
625+
azure_app_audience: "<app-audience>"
626+
jfrog_oidc_provider_name: "<oidc-provider-name>"
627+
628+
rbac:
629+
create: true
630+
631+
# Note: You must also create the service account and annotate it as described in Step 3B.2
632+
```
633+
634+
> **ℹ️ Note:** When using Workload Identity, ensure the service account `jfrog-provider-sa` is annotated with `JFrogExchange="true"` and the Azure App Client ID as shown in Step 3B.2.
635+
636+
450637
### 📦 Install with Helm
451638

452639
#### Add JFrog Helm repository
@@ -458,15 +645,24 @@ helm repo add jfrog https://charts.jfrog.io
458645
helm repo update
459646
```
460647

461-
And then install using the following command -
648+
#### Install the Credential Provider
649+
650+
**For Nodepool Managed Identity (Option A):**
462651

463652
```bash
464-
# Install the credential provider
465653
helm upgrade --install secret-provider jfrog/jfrog-credential-provider \
466654
--namespace jfrog \
467655
--create-namespace \
468-
-f ./examples/azure-values.yaml --devel
656+
-f ./examples/azure-values.yaml
657+
```
469658

659+
**For Workload Identity (Option B):**
660+
661+
```bash
662+
helm upgrade --install secret-provider jfrog/jfrog-credential-provider \
663+
--namespace jfrog \
664+
--create-namespace \
665+
-f ./examples/azure-projected-sa-values.yaml
470666
```
471667

472668
---

0 commit comments

Comments
 (0)