Skip to content

Commit 749f8bc

Browse files
authored
Merge 2ff72db into 7642fad
2 parents 7642fad + 2ff72db commit 749f8bc

File tree

10 files changed

+469
-325
lines changed

10 files changed

+469
-325
lines changed

.github/workflows/keyfactor-bootstrap-workflow.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ jobs:
1414
build:
1515
name: Build and Lint
1616
runs-on: ubuntu-latest
17-
timeout-minutes: 5
17+
timeout-minutes: 8
1818
steps:
19-
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
20-
- uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
19+
- uses: actions/checkout@v4
20+
- uses: actions/setup-go@v4.2.1
2121
with:
2222
go-version-file: 'go.mod'
2323
cache: true
@@ -35,9 +35,9 @@ jobs:
3535
timeout-minutes: 5
3636
steps:
3737
- name: Checkout
38-
uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
38+
uses: actions/checkout@v4
3939
- name: Set up Go 1.x
40-
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
40+
uses: actions/setup-go@v4.2.1
4141
with:
4242
go-version-file: 'go.mod'
4343
cache: true

README.md

Lines changed: 26 additions & 158 deletions
Large diffs are not rendered by default.

docs/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Keyfactor Docs
2+
3+
This is supplemental documentation for the [Keyfactor Command Cert Manager Issuer](../README.md). Please refer to the root-level README as the entrypoint for documentation regarding this integration.

docs/ambient-providers/azure.md

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
# Managed Identity Using Azure Entra ID Workload Identity (AKS)
2+
3+
This documentation is for instructions on using ambient credentials within Azure Kubernetes Services (AKS). Full documentation on Command Cert Manager Issuer can be found [here](../../README.md).
4+
5+
## Prerequisites
6+
7+
- [kubectl](https://kubernetes.io/docs/reference/kubectl/) installed on your machine and [connected to your AKS cluster](https://learn.microsoft.com/en-us/azure/aks/learn/quick-kubernetes-deploy-cli#connect-to-the-cluster)
8+
- [Helm](https://github.com/helm/helm?tab=readme-ov-file#install) 3.x installed
9+
- [Azure CLI](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest) installed and logged in
10+
11+
## Background
12+
13+
There are two types of [managed identities](https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/overview#managed-identity-types) that your Azure AKS workload may use:
14+
- System-assigned managed identity (MSI)
15+
- Automatically created and managed by Azure at the cluster level. This identity **can not** be shared with other Azure resources. This is used by default.
16+
- User-assigned managed identity (UAMI)
17+
- Created and managed by you. Identity **can** be shared with other Azure resources and associated with Kubernetes ServiceAccounts via Azure AD Workload Identity. Requires explicit workload identity configuration (show below).
18+
19+
Since you are using ambient credentials generated by your Azure AKS workload and targeting these credentials for your Command instance, you will need to create an [Azure App Registration](https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-register-app). We will walk through App Registration configuration in this document.
20+
21+
## System-Assigned Managed Identity (MSI)
22+
23+
By default, your AKS cluster is configured to use system-assigned managed identity. Your workload should automatically use the identity assigned to the cluster. You will need to set up the scope of the issuer to reference an app registration. Lastly, you will need to make sure the object ID of the managed identity is associated to a security claim in Keyfactor Command.
24+
25+
1. Install `cert-manager` to your AKS cluster. [Installation steps](https://cert-manager.io/docs/installation/helm/)
26+
1. Install `command-cert-manager-issuer` to your AKS cluster. [Installation steps](../../README.md#installing-command-issuer)
27+
1. Create an Azure App Registration. [Installation steps](#azure-app-registration)
28+
1. Deploy Issuer or ClusterIssuer Resource. [Installation steps](../../README.md#creating-issuer-and-clusterissuer-resources)
29+
- To use ambient credentials, do not supply a `commandSecretName` to your issuer's specification.
30+
- **IMPORTANT**: Fill in the `scopes` in your issuer's specification with the Application ID URI of your App Registration, suffixed with `./default`. Example:
31+
```yaml
32+
# Example issuer configuration
33+
spec:
34+
scopes: "api://your-app-registration-id/.default"
35+
```
36+
1. Add the system-assigned managed identity object ID to a security claim in Keyfactor Command
37+
```bash
38+
export AKS_CLUSTER_RESOURCE_GROUP="" # the resource group your AKS cluster is deployed to
39+
export AKS_CLUSTER_NAME="" # the name of your AKS cluster
40+
export CURRENT_TENANT=$(az account show --query tenantId --output tsv)
41+
42+
echo "AKS Cluster Resource Group: $AKS_CLUSTER_RESOURCE_GROUP"
43+
echo "AKS Cluster Name: $AKS_CLUSTER_NAME"
44+
45+
# Get the principal ID of your AKS cluster
46+
AKS_CLUSTER_OBJECT_ID=$(az aks show --resource-group $AKS_CLUSTER_RESOURCE_GROUP --name $AKS_CLUSTER_NAME --query "identityProfile.kubeletidentity.objectId" -o tsv)
47+
echo "AKS Cluster MSI Object ID: $AKS_CLUSTER_OBJECT_ID"
48+
49+
echo "View then OIDC configuration for the Entra OIDC token issuer: https://login.microsoftonline.com/$CURRENT_TENANT/v2.0/.well-known/openid-configuration"
50+
51+
echo "Authority: https://login.microsoftonline.com/$CURRENT_TENANT/v2.0"
52+
```
53+
54+
> **Note**: AKS workloads inherit the kubelet's managed identity, not the cluster's control plane identity. This is why we use `identityProfile.kubeletidentity.objectId` rather than `identity.principalId`.
55+
56+
You can map the object ID to an OAuth Subject or OAuth Object ID security claim in Keyfactor Command. Make sure the [security claim is associated to a security role](https://software.keyfactor.com/Core-OnPrem/Current/Content/ReferenceGuide/SecurityOverview.htm?Highlight=Security%20Roles) with the required permissions. Please refer to the [Configuring Command](../../README.md#configuring-command) **Configure Command Security Roles and Claims** section for security role requirements.
57+
58+
Make sure an identity provider is configured in Keyfactor Command with the authority set to the authority output above.
59+
60+
## User-Assigned Managed Identity (UAMI)
61+
62+
User-assigned managed identity configuration is more involved, but allows the identity to be shared across different AKS clusters. The AKS cluster will need to be configured to allow workload identity and the Command Issuer's ServiceAccount will need to reference the client ID of the user-assigned managed identity. You will need to make sure the principal ID of the user-assigned managed identity is associated to a security claim in Keyfactor Command.
63+
64+
1. Install `cert-manager` to your AKS cluster. [Installation steps](https://cert-manager.io/docs/installation/helm/)
65+
1. Enable OIDC and Workload Identity on your AKS cluster. [Learn more](https://learn.microsoft.com/en-us/azure/aks/workload-identity-deploy-cluster)
66+
```bash
67+
export AKS_CLUSTER_RESOURCE_GROUP="" # the resource group your AKS cluster is deployed to
68+
export AKS_CLUSTER_NAME="" # the name of your AKS cluster
69+
70+
echo "AKS Cluster Resource Group: $AKS_CLUSTER_RESOURCE_GROUP"
71+
echo "AKS Cluster Name: $AKS_CLUSTER_NAME"
72+
73+
echo "Enabling OIDC and workload identity on AKS cluster..."
74+
75+
az aks update \
76+
--name ${AKS_CLUSTER_NAME} \
77+
--resource-group ${AKS_CLUSTER_RESOURCE_GROUP} \
78+
--enable-oidc-issuer \
79+
--enable-workload-identity
80+
```
81+
1. Create a user-assigned managed identity
82+
```bash
83+
export UAMI_IDENTITY_NAME="command-issuer-uami" # the name you want to give your UAMI
84+
85+
echo "Creating user assigned managed identity $UAMI_IDENTITY_NAME..."
86+
87+
az identity create --name "${UAMI_IDENTITY_NAME}" --resource-group "${AKS_CLUSTER_RESOURCE_GROUP}"
88+
89+
export UAMI_CLIENT_ID=$(az identity show --name $UAMI_IDENTITY_NAME --resource-group $AKS_CLUSTER_RESOURCE_GROUP --query clientId --output tsv)
90+
91+
echo "Client ID of user-assigned managed identity: $UAMI_CLIENT_ID"
92+
```
93+
1. Deploy Command Cert Manager Issuer with ServiceAccount labeled to use workload identity and UAMI client ID
94+
95+
```bash
96+
export UAMI_CLIENT_ID=$(az identity show --name $UAMI_IDENTITY_NAME --resource-group $AKS_CLUSTER_RESOURCE_GROUP --query clientId --output tsv) # should be the same as the previous step
97+
98+
export ISSUER_NAMESPACE="command-issuer-system"
99+
100+
echo "Installing command-cert-manager issuer to namespace $ISSUER_NAMESPACE"
101+
echo "Labeling ServiceAccount to use workload identity with user-assigned-managed-identity client ID $UAMI_CLIENT_ID..."
102+
103+
helm install command-cert-manager-issuer command-issuer/command-cert-manager-issuer \
104+
--namespace $ISSUER_NAMESPACE \
105+
--create-namespace \
106+
--set "fullnameOverride=command-cert-manager-issuer" \
107+
--set-string "podLabels.azure\.workload\.identity/use=true" \
108+
--set-string "serviceAccount.labels.azure\.workload\.identity/use=true" \
109+
--set-string "serviceAccount.annotations.azure\.workload\.identity/client-id=${UAMI_CLIENT_ID}"
110+
```
111+
112+
113+
If successful, the Command Issuer Pod will have new environment variables and the Azure WI ServiceAccount token as a projected volume:
114+
115+
```shell
116+
kubectl -n command-issuer-system describe pod
117+
```
118+
119+
```shell
120+
Containers:
121+
command-cert-manager-issuer:
122+
...
123+
Environment:
124+
AZURE_CLIENT_ID: <UAMI_CLIENT_ID>
125+
AZURE_TENANT_ID: <GUID>
126+
AZURE_FEDERATED_TOKEN_FILE: /var/run/secrets/azure/tokens/azure-identity-token
127+
AZURE_AUTHORITY_HOST: https://login.microsoftonline.com/
128+
Mounts:
129+
/var/run/secrets/azure/tokens from azure-identity-token (ro)
130+
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-6rmzz (ro)
131+
...
132+
Volumes:
133+
...
134+
azure-identity-token:
135+
Type: Projected (a volume that contains injected data from multiple sources)
136+
TokenExpirationSeconds: 3600
137+
```
138+
1. Associate a Federated Identity Credential (FIC) with the User Assigned Managed Identity. The FIC allows Command Issuer to act on behalf of the Managed Identity by telling Azure to expect:
139+
- The `iss` claim of the ServiceAccount token to match the cluster's OIDC Issuer. Azure will also use the Issuer URL to download the JWT signing certificate.
140+
- The `sub` claim of the ServiceAccount token to match the ServiceAccount's name and namespace.
141+
142+
```shell
143+
export SERVICE_ACCOUNT_NAME=command-cert-manager-issuer # This is the default Kubernetes ServiceAccount used by the Command Issuer controller.
144+
export SERVICE_ACCOUNT_NAMESPACE=command-issuer-system # This is the default namespace for Command Issuer used in this doc.
145+
146+
export SERVICE_ACCOUNT_ISSUER=$(az aks show --resource-group $AKS_CLUSTER_RESOURCE_GROUP --name $AKS_CLUSTER_NAME --query "oidcIssuerProfile.issuerUrl" -o tsv)
147+
148+
echo "Service account issuer: $SERVICE_ACCOUNT_ISSUER"
149+
echo "Creating federated credentials for user-assigned managed identity $UAMI_IDENTITY_NAME in resource group $AKS_CLUSTER_RESOURCE_GROUP..."
150+
151+
az identity federated-credential create \
152+
--name "${UAMI_IDENTITY_NAME}-federated-credentials" \
153+
--identity-name "${UAMI_IDENTITY_NAME}" \
154+
--resource-group "${AKS_CLUSTER_RESOURCE_GROUP}" \
155+
--issuer "${SERVICE_ACCOUNT_ISSUER}" \
156+
--subject "system:serviceaccount:${SERVICE_ACCOUNT_NAMESPACE}:${SERVICE_ACCOUNT_NAME}" \
157+
--audiences "api://AzureADTokenExchange"
158+
```
159+
160+
> Read more about [Workload Identity federation](https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation) in the Entra ID documentation.
161+
>
162+
> Read more about [the `az identity federated-credential` command](https://learn.microsoft.com/en-us/cli/azure/identity/federated-credential?view=azure-cli-latest).
163+
1. Create an Azure App Registration. [Installation steps](#azure-app-registration)
164+
1. Deploy Issuer or ClusterIssuer Resource. [Installation steps](../../README.md#creating-issuer-and-clusterissuer-resources)
165+
- To use ambient credentials, do not supply a `commandSecretName` to your issuer's specification.
166+
- **IMPORTANT**: Fill in the `scopes` in your issuer's specification with the Application ID URI of your App Registration, suffixed with `./default`. Example:
167+
```yaml
168+
# Example issuer configuration
169+
spec:
170+
scopes: "api://your-app-registration-id/.default"
171+
```
172+
1. Add the user-assigned managed identity principal ID to a security claim in Keyfactor Command
173+
```shell
174+
export UAMI_PRINCIPAL_ID=$(az identity show --name $UAMI_IDENTITY_NAME --resource-group $AKS_CLUSTER_RESOURCE_GROUP --query principalId --output tsv)
175+
export CURRENT_TENANT=$(az account show --query tenantId --output tsv)
176+
echo "UAMI Principal ID: ${UAMI_PRINCIPAL_ID}"
177+
178+
echo "View then OIDC configuration for the Entra OIDC token issuer: https://login.microsoftonline.com/$CURRENT_TENANT/v2.0/.well-known/openid-configuration"
179+
180+
echo "Authority: https://login.microsoftonline.com/$CURRENT_TENANT/v2.0"
181+
```
182+
183+
You can map the principal ID to an OAuth Subject or OAuth Object ID security claim in Keyfactor Command. Make sure the [security claim is associated to a security role](https://software.keyfactor.com/Core-OnPrem/Current/Content/ReferenceGuide/SecurityOverview.htm?Highlight=Security%20Roles) with the required permissions. Please refer to the [Configuring Command](../../README.md#configuring-command) **Configure Command Security Roles and Claims** section for security role requirements.
184+
185+
Make sure an identity provider is configured in Keyfactor Command with the authority set to the authority output above.
186+
187+
188+
## Azure App Registration
189+
190+
The identity server that generates the access token from DefaultAzureCredentials requires a valid scope. The access token is being used for authorization on a resource outside of Azure (Keyfactor Command), so an app registration for Entra AD to represent an external application.
191+
192+
Here is official Azure documentation on how to [create an app registration](https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-register-app).
193+
194+
After the App Registration is created, expose an API. You can do this by going to Manage > Expose an API and editing the Application ID URI.
195+
196+
> IMPORTANT: The Application ID URI will be used in your `scopes` claim. Make sure to copy this value down. For example, if your Application ID URI is `api://abcd`, your scope value should be `api://abcd/.default`.
197+
198+
![Application ID URI](../assets/app-registration-app-id-uri.png)
199+
200+
### App Registration Assignment Requirement
201+
202+
By default, Azure App Registrations do not require an assignment in order for an identity to access to the application. However, there may be some compliance need to require an assignment for an identity to access your app registration. This option can be toggled via the Enterprise Application properties of your App Registration. If enabled, and your identity does not have an assignment to this application, you may see the error:
203+
204+
```
205+
AADSTS501051: Application '<identity-object-id>'(<identity-name>) is not assigned to a role for the application 'api://<application-id-uri>'(<application-name>)
206+
```
207+
208+
![App Registration Assignment Required](../assets/app-registration-assignment-required.png)
209+
210+
For more information about the assignment requirement for app registrations and how this can affect your identities, please see [this blog post](https://mderriey.com/2019/04/19/aad-apps-user-assignment-required/).

docs/ambient-providers/google.md

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Google Kubernetes Engine (GKE) Workload Identity
2+
3+
This documentation is for instructions on using ambient credentials within Google Kubernetes Engine (GKE). Full documentation on Command Cert Manager Issuer can be found [here](../../README.md).
4+
5+
## Prerequisites
6+
7+
- [cert-manager](https://cert-manager.io/docs/installation/helm/) installed to your GKE cluster.
8+
- [command-cert-manager-issuer](../../README.md#installing-command-issuer) installed to your GKE cluster.
9+
- [Issuer or ClusterIssuer](../../README.md#creating-issuer-and-clusterissuer-resources) resources deployed to your GKE cluster.
10+
- to use ambient credentials, do not supply a `commandSecretName` to your issuer's specification. `scopes` and `audience` fields are optional.
11+
- [Gcloud CLI](https://cloud.google.com/sdk/docs/install) installed and logged in
12+
13+
## Background
14+
15+
Google Kuberentes Engine (GKE) supports the ability to authenticate your GKE workloads using workload identity.
16+
17+
By default, GKE clusters are assigned the [default service account](https://cloud.google.com/compute/docs/access/service-accounts#token) for your Google project. This service account is used to generate an ID token for your workload. However, you may opt to use [Workload Identity Federation](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity#metadata-server) to your GKE cluster.
18+
19+
## How to use Workload Identity
20+
21+
1. Get the OAuth Client and Identity Provider for your GKE Cluster
22+
23+
Regardless if you are using the default service account or a custom service account, the following script will help you derive your GKE cluster's OAuth Client:
24+
25+
```shell
26+
export CLUSTER_NAME="" # name of your GKE cluster
27+
export GCLOUD_REGION="" # region your cluster is hosted in
28+
export GCLOUD_PROJECT_ID=$(gcloud config get-value project) # populate with the current PROJECT_ID context
29+
export GCLOUD_PROJECT_NUMBER=$(gcloud projects describe $GCLOUD_PROJECT_ID --format="value(projectNumber)")
30+
31+
export GCLOUD_SERVICE_ACCOUNT=$(gcloud container clusters describe $CLUSTER_NAME \
32+
--zone $GCLOUD_REGION \
33+
--format="value(nodeConfig.serviceAccount)")
34+
35+
echo "Cluster name: $CLUSTER_NAME"
36+
echo "Region: $GCLOUD_REGION"
37+
echo "Project ID: $GCLOUD_PROJECT_ID"
38+
echo "Project Number: $GCLOUD_PROJECT_NUMBER"
39+
40+
if [[ "$GCLOUD_SERVICE_ACCOUNT" == "default" ]]; then
41+
echo "Overriding service account..."
42+
# Override service account with default compute service account
43+
GCLOUD_SERVICE_ACCOUNT="$GCLOUD_PROJECT_NUMBER[email protected]"
44+
fi
45+
46+
echo "Service account: $GCLOUD_SERVICE_ACCOUNT"
47+
48+
# Get OAuth2 Client ID of service account
49+
export GCLOUD_SERVICE_ACCOUNT_CLIENT_ID=$(gcloud iam service-accounts describe $GCLOUD_SERVICE_ACCOUNT \
50+
--format="value(oauth2ClientId)")
51+
52+
echo "Service account OAuth2 client ID: $GCLOUD_SERVICE_ACCOUNT_CLIENT_ID"
53+
54+
echo "View the OIDC configuration for Google's OIDC token issuer: https://accounts.google.com/.well-known/openid-configuration"
55+
56+
echo "Authority: https://accounts.google.com"
57+
```
58+
59+
2. Add Google as an [Identity Provider in Command](https://software.keyfactor.com/Core-OnPrem/Current/Content/ReferenceGuide/IdentityProviders.htm?Highlight=identity%20provider) using the identity provider information from the previous step, and [add the Service Account's OAuth Client ID as an `OAuth Subject` claim to the Security Role](https://software.keyfactor.com/Core-OnPrem/Current/Content/ReferenceGuide/SecurityOverview.htm?Highlight=Security%20Roles) created/identified earlier.
201 KB
Loading
285 KB
Loading

0 commit comments

Comments
 (0)