mirror of
https://github.com/openshift/openshift-docs.git
synced 2026-02-05 12:46:18 +01:00
Merge pull request #98806 from wgabor0427/OSDOCS-16120
OSDOCS-16120 creating new modules from a module that had too many procedures
This commit is contained in:
@@ -1233,11 +1233,11 @@ Topics:
|
||||
File: zero-trust-manager-configuration
|
||||
- Name: Configuring Zero Trust Workload Identity Manager OIDC Federation
|
||||
File: zero-trust-manager-oidc-federation
|
||||
- Name: Monitoring Zero Trust Workload Identity Manager
|
||||
File: zero-trust-manager-monitoring
|
||||
- Name: Enabling create-only mode for the Zero Trust Workload Identity Manager
|
||||
File: zero-trust-manager-reconciliation
|
||||
- Name: Uninstalling Zero Trust Workload Identity Manager
|
||||
- Name: Monitoring Zero Trust Workload Identity Manager
|
||||
File: zero-trust-manager-monitoring
|
||||
- Name: Uninstalling the Zero Trust Workload Identity Manager
|
||||
File: zero-trust-manager-uninstall
|
||||
- Name: External Secrets Operator for Red Hat OpenShift
|
||||
Dir: external_secrets_operator
|
||||
|
||||
39
modules/zero-trust-manager-config-azure-blob.adoc
Normal file
39
modules/zero-trust-manager-config-azure-blob.adoc
Normal file
@@ -0,0 +1,39 @@
|
||||
// Module included in the following assemblies:
|
||||
//
|
||||
// * security/zero_trust_workload_identity_manageer/zero-trust-manager-oidc-federation.adoc
|
||||
|
||||
:_mod-docs-content-type: PROCEDURE
|
||||
[id="zero-trust-manager-configure-azure-blob_{context}"]
|
||||
= Configuring Azure blob storage
|
||||
|
||||
You need to create a new storage account to be used to store content.
|
||||
|
||||
.Procedure
|
||||
|
||||
. Create a new storage account that is used to store content by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ az storage account create \
|
||||
--name ${STORAGE_ACCOUNT} \
|
||||
--resource-group ${RESOURCE_GROUP} \
|
||||
--location ${LOCATION} \
|
||||
--encryption-services blob
|
||||
----
|
||||
|
||||
. Obtain the storage ID for the newly created storage account by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export STORAGE_ACCOUNT_ID=$(az storage account show -n ${STORAGE_ACCOUNT} -g ${RESOURCE_GROUP} --query id --out tsv)
|
||||
----
|
||||
|
||||
. Create a storage container inside the newly created storage account to provide a location to support the storage of blobs by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ az storage container create \
|
||||
--account-name ${STORAGE_ACCOUNT} \
|
||||
--name ${STORAGE_CONTAINER} \
|
||||
--auth-mode login
|
||||
----
|
||||
39
modules/zero-trust-manager-config-azure-identity.adoc
Normal file
39
modules/zero-trust-manager-config-azure-identity.adoc
Normal file
@@ -0,0 +1,39 @@
|
||||
// Module included in the following assemblies:
|
||||
//
|
||||
// * security/zero_trust_workload_identity_manageer/zero-trust-manager-oidc-federation.adoc
|
||||
|
||||
:_mod-docs-content-type: PROCEDURE
|
||||
[id="zero-trust-manager-configure-azure-identity_{context}"]
|
||||
= Configuring an Azure user managed identity
|
||||
|
||||
You need to Create a new User Managed Identity and then obtain the Client ID of the related Service Principal associated with the User Managed Identity.
|
||||
|
||||
.Procedure
|
||||
|
||||
. Create a new User Managed Identity and then obtain the Client ID of the related Service Principal associated with the User Managed Identity by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ az identity create \
|
||||
--name ${USER_ASSIGNED_IDENTITY_NAME} \
|
||||
--resource-group ${RESOURCE_GROUP}
|
||||
|
||||
$ export IDENTITY_CLIENT_ID=$(az identity show --resource-group "${RESOURCE_GROUP}" --name "${USER_ASSIGNED_IDENTITY_NAME}" --query 'clientId' -otsv)
|
||||
----
|
||||
|
||||
. Retrieve the `CLIENT_ID` of an Azure user-assigned managed identity and save it as an environment variable by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export IDENTITY_CLIENT_ID=$(az identity show --resource-group "${RESOURCE_GROUP}" --name "${USER_ASSIGNED_IDENTITY_NAME}" --query 'clientId' -otsv)
|
||||
----
|
||||
|
||||
. Associate a role with the Service Principal associated with the User Managed Identity by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ az role assignment create \
|
||||
--role "Storage Blob Data Contributor" \
|
||||
--assignee "${IDENTITY_CLIENT_ID}" \
|
||||
--scope ${STORAGE_ACCOUNT_ID}
|
||||
----
|
||||
@@ -3,7 +3,7 @@
|
||||
// * security/zero_trust_workload_identity_manageer/zero-trust-manager-oidc-federation.adoc
|
||||
|
||||
:_mod-docs-content-type: PROCEDURE
|
||||
[id="zero-trust-manager-configure-aws_{context}"]
|
||||
[id="zero-trust-manager-configure-azure_{context}"]
|
||||
= Using Entra ID with {azure-first}
|
||||
|
||||
After the Entra ID configuration is complete, you can set up Entra ID to work with {azure-short}.
|
||||
@@ -12,8 +12,6 @@ After the Entra ID configuration is complete, you can set up Entra ID to work wi
|
||||
|
||||
* You have configured the SPIRE OIDC Discovery Provider Route to serve the TLS certificates from a publicly trusted CA.
|
||||
|
||||
== Configuring an {azure-short} account
|
||||
|
||||
.Procedure
|
||||
|
||||
. Log in to Azure by running the following command:
|
||||
@@ -23,12 +21,20 @@ After the Entra ID configuration is complete, you can set up Entra ID to work wi
|
||||
$ az login
|
||||
----
|
||||
|
||||
. Configure variables for your Azure subscription and tenant:
|
||||
. Configure variables for your Azure subscription and tenant by running the following commands:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export SUBSCRIPTION_ID=$(az account list --query "[?isDefault].id" -o tsv) <1>
|
||||
----
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export TENANT_ID=$(az account list --query "[?isDefault].tenantId" -o tsv) <2>
|
||||
----
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export LOCATION=centralus <3>
|
||||
----
|
||||
+
|
||||
@@ -36,14 +42,30 @@ $ export LOCATION=centralus <3>
|
||||
<2> The ID for your Azure Active Directory instance.
|
||||
<3> The Azure region where your resource is created.
|
||||
|
||||
. Define resource variable names.
|
||||
. Define resource variable names by running the following commands:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export NAME=ztwim <1>
|
||||
----
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export RESOURCE_GROUP="${NAME}-rg" <2>
|
||||
----
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export STORAGE_ACCOUNT="${NAME}storage" <3>
|
||||
----
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export STORAGE_CONTAINER="${NAME}storagecontainer" <4>
|
||||
----
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export USER_ASSIGNED_IDENTITY_NAME="${NAME}-identity" <5>
|
||||
----
|
||||
+
|
||||
@@ -53,7 +75,7 @@ $ export USER_ASSIGNED_IDENTITY_NAME="${NAME}-identity" <5>
|
||||
<4> The name for the storage container.
|
||||
<5> The name for a managed identity.
|
||||
|
||||
. Create the resource group.
|
||||
. Create the resource group by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
@@ -62,270 +84,3 @@ $ az group create \
|
||||
--location "${LOCATION}"
|
||||
----
|
||||
|
||||
== Configuring Azure blob storage
|
||||
|
||||
.Procedure
|
||||
|
||||
. Create a new storage account that is used to store content.
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ az storage account create \
|
||||
--name ${STORAGE_ACCOUNT} \
|
||||
--resource-group ${RESOURCE_GROUP} \
|
||||
--location ${LOCATION} \
|
||||
--encryption-services blob
|
||||
----
|
||||
|
||||
. Obtain the storage ID for the newly created storage account.
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export STORAGE_ACCOUNT_ID=$(az storage account show -n ${STORAGE_ACCOUNT} -g ${RESOURCE_GROUP} --query id --out tsv)
|
||||
----
|
||||
|
||||
. Create a storage container inside the newly created Storage Account to provide a location to support the storage of blobs.
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ az storage container create \
|
||||
--account-name ${STORAGE_ACCOUNT} \
|
||||
--name ${STORAGE_CONTAINER} \
|
||||
--auth-mode login
|
||||
----
|
||||
|
||||
== Configuring an Azure user managed identity
|
||||
|
||||
.Procedure
|
||||
|
||||
. Create a new User Managed Identity and then obtain the Client ID of the related Service Principal associated with the User Managed Identity.
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ az identity create \
|
||||
--name ${USER_ASSIGNED_IDENTITY_NAME} \
|
||||
--resource-group ${RESOURCE_GROUP}
|
||||
|
||||
$ export IDENTITY_CLIENT_ID=$(az identity show --resource-group "${RESOURCE_GROUP}" --name "${USER_ASSIGNED_IDENTITY_NAME}" --query 'clientId' -otsv)
|
||||
----
|
||||
|
||||
. Associate a role with the Service Principal associated with the User Managed Identity.
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ az role assignment create \
|
||||
--role "Storage Blob Data Contributor" \
|
||||
--assignee "${IDENTITY_CLIENT_ID}" \
|
||||
--scope ${STORAGE_ACCOUNT_ID}
|
||||
----
|
||||
|
||||
== Creating the demonstration application
|
||||
|
||||
.Procedure
|
||||
|
||||
. Set the application name and namespace.
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export APP_NAME=workload-app
|
||||
$ export APP_NAMESPACE=demo
|
||||
----
|
||||
|
||||
. Create the namespace.
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc create namespace $APP_NAMESPACE
|
||||
----
|
||||
|
||||
. Create the application Secret.
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc apply -f - << EOF
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: $APP_NAME
|
||||
namespace: $APP_NAMESPACE
|
||||
stringData:
|
||||
AAD_AUTHORITY: https://login.microsoftonline.com/
|
||||
AZURE_AUDIENCE: "api://AzureADTokenExchange"
|
||||
AZURE_TENANT_ID: "${TENANT_ID}"
|
||||
AZURE_CLIENT_ID: "${IDENTITY_CLIENT_ID}"
|
||||
BLOB_STORE_ACCOUNT: "${STORAGE_ACCOUNT}"
|
||||
BLOB_STORE_CONTAINER: "${STORAGE_CONTAINER}"
|
||||
EOF
|
||||
----
|
||||
|
||||
== Deploying the workload application
|
||||
|
||||
.Procedure
|
||||
|
||||
. To deploy the application, copy the entire command block provided and paste it directly into your terminal. Press *Enter*.
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc apply -f - << EOF
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: $APP_NAME
|
||||
namespace: $APP_NAMESPACE
|
||||
---
|
||||
kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
metadata:
|
||||
name: $APP_NAME
|
||||
namespace: $APP_NAMESPACE
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: $APP_NAME
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: $APP_NAME
|
||||
deployment: $APP_NAME
|
||||
spec:
|
||||
serviceAccountName: $APP_NAME
|
||||
containers:
|
||||
- name: $APP_NAME
|
||||
image: "registry.redhat.io/ubi9/python-311:latest"
|
||||
command:
|
||||
- /bin/bash
|
||||
- "-c"
|
||||
- |
|
||||
#!/bin/bash
|
||||
pip install spiffe azure-cli
|
||||
|
||||
cat << EOF > /opt/app-root/src/get-spiffe-token.py
|
||||
#!/opt/app-root/bin/python
|
||||
from spiffe import JwtSource
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser(description='Retrieve SPIFFE Token.')
|
||||
parser.add_argument("-a", "--audience", help="The audience to include in the token", required=True)
|
||||
args = parser.parse_args()
|
||||
with JwtSource() as source:
|
||||
jwt_svid = source.fetch_svid(audience={args.audience})
|
||||
print(jwt_svid.token)
|
||||
EOF
|
||||
|
||||
chmod +x /opt/app-root/src/get-spiffe-token.py
|
||||
while true; do sleep 10; done
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: $APP_NAME
|
||||
env:
|
||||
- name: SPIFFE_ENDPOINT_SOCKET
|
||||
value: unix:///run/spire/sockets/spire-agent.sock
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
readOnlyRootFilesystem: false
|
||||
runAsNonRoot: true
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
protocol: TCP
|
||||
volumeMounts:
|
||||
- name: spiffe-workload-api
|
||||
mountPath: /run/spire/sockets
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: spiffe-workload-api
|
||||
csi:
|
||||
driver: csi.spiffe.io
|
||||
readOnly: true
|
||||
EOF
|
||||
----
|
||||
|
||||
.Verification
|
||||
. Ensure that the `workload-app` pod is running successfully.
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc get pods -n $APP_NAMESPACE
|
||||
----
|
||||
+
|
||||
.Example output
|
||||
[source, terminal]
|
||||
----
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
workload-app-5f8b9d685b-abcde 1/1 Running 0 60s
|
||||
----
|
||||
|
||||
. Retrieve the SPIFFE JWT Token (SVID-JWT)
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
# Get the pod name dynamically
|
||||
$ POD_NAME=$(oc get pods -n $APP_NAMESPACE -l app=$APP_NAME -o jsonpath='{.items[0].metadata.name}')
|
||||
|
||||
# Execute the script inside the pod
|
||||
$ oc exec -it $POD_NAME -n $APP_NAMESPACE -- \
|
||||
/opt/app-root/src/get-spiffe-token.py -a "api://AzureADTokenExchange"
|
||||
----
|
||||
|
||||
== Configuring Azure with the SPIFFE identity federation
|
||||
|
||||
.Procedure
|
||||
|
||||
* Federate the identities between the User Managed Identity and the SPIFFE identity associated with the workload application.
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ az identity federated-credential create \
|
||||
--name ${NAME} \
|
||||
--identity-name ${USER_ASSIGNED_IDENTITY_NAME} \
|
||||
--resource-group ${RESOURCE_GROUP} \
|
||||
--issuer https://$JWT_ISSUER_ENDPOINT \
|
||||
--subject spiffe://$APP_DOMAIN/ns/$APP_NAMESPACE/sa/$APP_NAME \
|
||||
--audience api://AzureADTokenExchange
|
||||
----
|
||||
|
||||
== Verifying that the application workload can access the content in the Azure Blob Storage
|
||||
|
||||
.Procedure
|
||||
|
||||
. Retrieve a JWT token from the SPIFFE Workload API and login to the Azure CLI included within the pod.
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc rsh -n $APP_NAMESPACE deployment/$APP_NAME
|
||||
|
||||
$ export TOKEN=$(/opt/app-root/src/get-spiffe-token.py --audience=$AZURE_AUDIENCE)
|
||||
$ az login --service-principal \
|
||||
-t ${AZURE_TENANT_ID} \
|
||||
-u ${AZURE_CLIENT_ID} \
|
||||
--federated-token ${TOKEN}
|
||||
----
|
||||
|
||||
. Create a new file with the application workload pod and upload the file to the Blob Storage.
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ echo “Hello from OpenShift” > openshift-spire-federated-identities.txt
|
||||
$ az storage blob upload \
|
||||
--account-name ${BLOB_STORE_ACCOUNT} \
|
||||
--container-name ${BLOB_STORE_CONTAINER} \
|
||||
--name openshift-spire-federated-identities.txt \
|
||||
--file openshift-spire-federated-identities.txt \
|
||||
--auth-mode login
|
||||
----
|
||||
|
||||
.Verification
|
||||
* Confirm the file uploaded successfully by listing the files contained.
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ az storage blob list \
|
||||
--account-name ${BLOB_STORE_ACCOUNT} \
|
||||
--container-name ${BLOB_STORE_CONTAINER} \
|
||||
--auth-mode login \
|
||||
-o table
|
||||
----
|
||||
|
||||
|
||||
52
modules/zero-trust-manager-create-demo-app.adoc
Normal file
52
modules/zero-trust-manager-create-demo-app.adoc
Normal file
@@ -0,0 +1,52 @@
|
||||
// Module included in the following assemblies:
|
||||
//
|
||||
// * security/zero_trust_workload_identity_manageer/zero-trust-manager-oidc-federation.adoc
|
||||
|
||||
:_mod-docs-content-type: PROCEDURE
|
||||
[id="zero-trust-manager-create-demo-app_{context}"]
|
||||
= Creating the demonstration application
|
||||
|
||||
The demonstration application provides you a way to see if the entire system works.
|
||||
|
||||
.Procedure
|
||||
|
||||
To create the demonstration application, complete the following steps:
|
||||
|
||||
. Set the application name and namespace by running the following commands:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export APP_NAME=workload-app
|
||||
----
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export APP_NAMESPACE=demo
|
||||
----
|
||||
|
||||
. Create the namespace by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc create namespace $APP_NAMESPACE
|
||||
----
|
||||
|
||||
. Create the application Secret by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc apply -f - << EOF
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: $APP_NAME
|
||||
namespace: $APP_NAMESPACE
|
||||
stringData:
|
||||
AAD_AUTHORITY: https://login.microsoftonline.com/
|
||||
AZURE_AUDIENCE: "api://AzureADTokenExchange"
|
||||
AZURE_TENANT_ID: "${TENANT_ID}"
|
||||
AZURE_CLIENT_ID: "${IDENTITY_CLIENT_ID}"
|
||||
BLOB_STORE_ACCOUNT: "${STORAGE_ACCOUNT}"
|
||||
BLOB_STORE_CONTAINER: "${STORAGE_CONTAINER}"
|
||||
EOF
|
||||
----
|
||||
@@ -41,7 +41,7 @@ $ oc create rolebinding secret-reader-binding \
|
||||
-n zero-trust-workload-identity-manager
|
||||
----
|
||||
|
||||
. Configure the `SpireOIDCDIscoveryProvider` Custom Resource (CR) object to reference the Secret generated in the earlier step.
|
||||
. Configure the `SpireOIDCDIscoveryProvider` Custom Resource (CR) object to reference the Secret generated in the earlier step by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
@@ -53,14 +53,14 @@ spec:
|
||||
|
||||
.Verification
|
||||
|
||||
. In the `SpireOIDCDiscoveryProvider` CR, check if the `ManageRouteReady` condition is set to `True`.
|
||||
. In the `SpireOIDCDiscoveryProvider` CR, check if the `ManageRouteReady` condition is set to `True` by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc wait --for=jsonpath='{.status.conditions[?(@.type=="ManagedRouteReady")].status}'=True SpireOIDCDiscoveryProvider/cluster --timeout=120s
|
||||
----
|
||||
|
||||
. Verify that the OIDC endpoint can be accessed securely through HTTPS.
|
||||
. Verify that the OIDC endpoint can be accessed securely through HTTPS by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
@@ -82,17 +82,3 @@ $ curl https://$JWT_ISSUER_ENDPOINT/.well-known/openid-configuration
|
||||
}%
|
||||
----
|
||||
|
||||
== Disabling a managed route
|
||||
|
||||
If you want to fully control the behavior of exposing the OIDC Discovery Provider service, you can disable the managed Route based on your requirements.
|
||||
|
||||
.Procedure
|
||||
|
||||
* To manually configure the OIDC Discovery Provider, set `managedRoute` to `false`.
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc patch SpireOIDCDiscoveryProvider cluster --type=merge -p='
|
||||
spec:
|
||||
managedRoute: "false"
|
||||
----
|
||||
|
||||
128
modules/zero-trust-manager-deploy-app.adoc
Normal file
128
modules/zero-trust-manager-deploy-app.adoc
Normal file
@@ -0,0 +1,128 @@
|
||||
// Module included in the following assemblies:
|
||||
//
|
||||
// * security/zero_trust_workload_identity_manageer/zero-trust-manager-oidc-federation.adoc
|
||||
|
||||
:_mod-docs-content-type: PROCEDURE
|
||||
[id="zero-trust-manager-deploy-app_{context}"]
|
||||
= Deploying the workload application
|
||||
|
||||
Once the demonstration application has been created.
|
||||
|
||||
.Prerequisites
|
||||
|
||||
* The demonstration application has been created and deployed.
|
||||
|
||||
.Procedure
|
||||
|
||||
. To deploy the application, copy the entire command block provided and paste it directly into your terminal. Press *Enter*.
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc apply -f - << EOF
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: $APP_NAME
|
||||
namespace: $APP_NAMESPACE
|
||||
---
|
||||
kind: Deployment
|
||||
apiVersion: apps/v1
|
||||
metadata:
|
||||
name: $APP_NAME
|
||||
namespace: $APP_NAMESPACE
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: $APP_NAME
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: $APP_NAME
|
||||
deployment: $APP_NAME
|
||||
spec:
|
||||
serviceAccountName: $APP_NAME
|
||||
containers:
|
||||
- name: $APP_NAME
|
||||
image: "registry.redhat.io/ubi9/python-311:latest"
|
||||
command:
|
||||
- /bin/bash
|
||||
- "-c"
|
||||
- |
|
||||
#!/bin/bash
|
||||
pip install spiffe azure-cli
|
||||
|
||||
cat << EOF > /opt/app-root/src/get-spiffe-token.py
|
||||
#!/opt/app-root/bin/python
|
||||
from spiffe import JwtSource
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser(description='Retrieve SPIFFE Token.')
|
||||
parser.add_argument("-a", "--audience", help="The audience to include in the token", required=True)
|
||||
args = parser.parse_args()
|
||||
with JwtSource() as source:
|
||||
jwt_svid = source.fetch_svid(audience={args.audience})
|
||||
print(jwt_svid.token)
|
||||
EOF
|
||||
|
||||
chmod +x /opt/app-root/src/get-spiffe-token.py
|
||||
while true; do sleep 10; done
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: $APP_NAME
|
||||
env:
|
||||
- name: SPIFFE_ENDPOINT_SOCKET
|
||||
value: unix:///run/spire/sockets/spire-agent.sock
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
readOnlyRootFilesystem: false
|
||||
runAsNonRoot: true
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
protocol: TCP
|
||||
volumeMounts:
|
||||
- name: spiffe-workload-api
|
||||
mountPath: /run/spire/sockets
|
||||
readOnly: true
|
||||
volumes:
|
||||
- name: spiffe-workload-api
|
||||
csi:
|
||||
driver: csi.spiffe.io
|
||||
readOnly: true
|
||||
EOF
|
||||
----
|
||||
|
||||
.Verification
|
||||
. Ensure that the `workload-app` pod is running successfully by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc get pods -n $APP_NAMESPACE
|
||||
----
|
||||
+
|
||||
.Example output
|
||||
[source, terminal]
|
||||
----
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
workload-app-5f8b9d685b-abcde 1/1 Running 0 60s
|
||||
----
|
||||
|
||||
. Retrieve the SPIFFE JWT Token (SVID-JWT):
|
||||
|
||||
.. Get the pod name dynamically by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ POD_NAME=$(oc get pods -n $APP_NAMESPACE -l app=$APP_NAME -o jsonpath='{.items[0].metadata.name}')
|
||||
----
|
||||
|
||||
.. Run the script inside the pod by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc exec -it $POD_NAME -n $APP_NAMESPACE -- \
|
||||
/opt/app-root/src/get-spiffe-token.py -a "api://AzureADTokenExchange"
|
||||
----
|
||||
20
modules/zero-trust-manager-disabling-route.adoc
Normal file
20
modules/zero-trust-manager-disabling-route.adoc
Normal file
@@ -0,0 +1,20 @@
|
||||
// Module included in the following assemblies:
|
||||
//
|
||||
// * security/zero_trust_workload_identity_manageer/zero-trust-manager-oidc-federation.adoc
|
||||
|
||||
:_mod-docs-content-type: PROCEDURE
|
||||
[id="zero-trust-manager-disabling-route_{context}"]
|
||||
= Disabling a managed route
|
||||
|
||||
If you want to fully control the behavior of exposing the OIDC Discovery Provider service, you can disable the managed Route based on your requirements.
|
||||
|
||||
.Procedure
|
||||
|
||||
* To manually configure the OIDC Discovery Provider, set `managedRoute` to `false` by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc patch SpireOIDCDiscoveryProvider cluster --type=merge -p='
|
||||
spec:
|
||||
managedRoute: "false"
|
||||
----
|
||||
@@ -5,7 +5,7 @@
|
||||
:_mod-docs-content-type: PROCEDURE
|
||||
[id="zero-trust-manager-initialize-vault-oidc_{context}"]
|
||||
|
||||
= Initializing Vault
|
||||
= Initializing and unsealing Vault
|
||||
|
||||
A newly installed Vault is sealed. This means that the primary encryption key, which protects all other encryption keys, is not loaded into the server memory upon startup. You need to initialize Vault to unseal it.
|
||||
|
||||
@@ -27,40 +27,42 @@ The steps to initialize a Vault server are:
|
||||
|
||||
* Ensure that Vault is not initialized. You can only initialize a Vault server once.
|
||||
|
||||
== Initializing and unsealing Vault
|
||||
|
||||
.Procedure
|
||||
|
||||
. Open a remote shell into the `vault` pod:
|
||||
. Open a remote shell into the `vault` pod by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc rsh -n vault statefulset/vault
|
||||
----
|
||||
|
||||
. Initialize Vault to get your unseal key and root token:
|
||||
. Initialize Vault to get your unseal key and root token by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ vault operator init -key-shares=1 -key-threshold=1 -format=json
|
||||
----
|
||||
|
||||
. Export the unseal key and root token you received from the earlier command:
|
||||
. Export the unseal key and root token you received from the earlier command by running the following commands:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export UNSEAL_KEY=<Your-Unseal-Key>
|
||||
----
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export ROOT_TOKEN=<Your-Root-Token>
|
||||
----
|
||||
|
||||
. Unseal Vault using your unseal key:
|
||||
. Unseal Vault using your unseal key by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ vault operator unseal -format=json $UNSEAL_KEY
|
||||
----
|
||||
|
||||
. Exit the pod by entering `Exit`.
|
||||
. Exit the pod by entering `exit`.
|
||||
|
||||
.Verification
|
||||
|
||||
@@ -78,203 +80,7 @@ NAME READY STATUS RESTARTS AGE
|
||||
vault-0 1/1 Running 0 65d
|
||||
----
|
||||
|
||||
== Enabling the key-value secrets engine and store a test secret
|
||||
|
||||
.Procedure
|
||||
|
||||
. Open another shell session in the `Vault` pod.
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc rsh -n vault statefulset/vault
|
||||
----
|
||||
|
||||
. Export your root token again within this new session and log in:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export ROOT_TOKEN=<Your-Root-Token>
|
||||
$ vault login "${ROOT_TOKEN}"
|
||||
----
|
||||
|
||||
. Enable the KV secrets engine at the `secret/` path and create a test secret:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export NAME=ztwim
|
||||
$ vault secrets enable -path=secret kv
|
||||
$ vault kv put secret/$NAME version=v0.1.0
|
||||
----
|
||||
|
||||
.Verification
|
||||
|
||||
* To verify that the secret is stored correctly, run the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ vault kv get secret/$NAME
|
||||
----
|
||||
|
||||
== Configuring JSON Web Token authentication with SPIRE
|
||||
|
||||
You need to set up JSON Web Token (JWT) authentication so your applications can securely log in to Vault by using SPIFFE identities.
|
||||
|
||||
.Procedure
|
||||
|
||||
. On your local machine, retrieve the SPIRE Certificate Authority (CA) bundle and save it to a file:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc get cm -n zero-trust-workload-identity-manager spire-bundle -o jsonpath='{ .data.bundle\.crt }' > oidc_provider_ca.pem
|
||||
----
|
||||
|
||||
. Back in the Vault pod shell, create a temporary file and paste the contents of `oidc_provider_ca.pem` into it:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ cat << EOF > /tmp/oidc_provider_ca.pem
|
||||
-----BEGIN CERTIFICATE-----
|
||||
<Paste-Your-Certificate-Content-Here>
|
||||
-----END CERTIFICATE-----
|
||||
EOF
|
||||
----
|
||||
|
||||
. Set up the necessary environment variables for the JWT configuration:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export APP_DOMAIN=<Your-App-Domain>
|
||||
$ export JWT_ISSUER_ENDPOINT="oidc-discovery.$APP_DOMAIN"
|
||||
$ export OIDC_URL="https://$JWT_ISSUER_ENDPOINT"
|
||||
$ export OIDC_CA_PEM="$(cat /tmp/oidc_provider_ca.pem)"
|
||||
----
|
||||
|
||||
. Enable the JWT authentication method and configure it with your OIDC provider details:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export ROLE="${NAME}-role"
|
||||
$ vault auth enable jwt
|
||||
$ vault write auth/jwt/config \
|
||||
oidc_discovery_url=$OIDC_URL \
|
||||
oidc_discovery_ca_pem="$OIDC_CA_PEM" \
|
||||
default_role=$ROLE
|
||||
----
|
||||
|
||||
. Create a policy named `ztwim-policy` that grants read access to the secret you created earlier:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export POLICY="${NAME}-policy"
|
||||
$ vault policy write $POLICY -<<EOF
|
||||
path "secret/$NAME" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
EOF
|
||||
----
|
||||
|
||||
. Create a JWT role that binds the policy to workload with a specific SPIFFE ID:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export APP_NAME=client
|
||||
$ export APP_NAMESPACE=demo
|
||||
$ export AUDIENCE=$APP_NAME
|
||||
$ vault write auth/jwt/role/$ROLE -<<EOF
|
||||
{
|
||||
"role_type": "jwt",
|
||||
"user_claim": "sub",
|
||||
"bound_audiences": "$AUDIENCE",
|
||||
"bound_claims_type": "glob",
|
||||
"bound_claims": {
|
||||
"sub": "spiffe://$APP_DOMAIN/ns/$APP_NAMESPACE/sa/$APP_NAME"
|
||||
},
|
||||
"token_ttl": "24h",
|
||||
"token_policies": "$POLICY"
|
||||
}
|
||||
EOF
|
||||
----
|
||||
|
||||
== Deploying a demo application
|
||||
|
||||
This creates a simple client application that uses its SPIFFE identity to authenticate with Vault.
|
||||
|
||||
.Procedure
|
||||
|
||||
. On your local machine, set the environment variables for your application:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export APP_NAME=client
|
||||
$ export APP_NAMESPACE=demo
|
||||
$ export AUDIENCE=$APP_NAME
|
||||
----
|
||||
|
||||
. Apply the Kubernetes manifest to create the namespace, service account, and deployment for the demo app. This deployment mounts the SPIFFE CSI driver socket.
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc apply -f - <<EOF
|
||||
# ... (paste the full YAML from your provided code here) ...
|
||||
EOF
|
||||
----
|
||||
|
||||
.Verification
|
||||
|
||||
* Verify that the client deployment is ready by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc get deploy -n $APP_NAMESPACE
|
||||
----
|
||||
+
|
||||
.Example output
|
||||
[source, terminal]
|
||||
----
|
||||
NAME READY UP-TO-DATE AVAILABLE AGE
|
||||
frontend-app 2/2 2 2 120d
|
||||
backend-api 3/3 3 3 120d
|
||||
----
|
||||
|
||||
== Authenticating and retrieving the secret
|
||||
|
||||
You use the demo app to fetch a JWT token from the SPIFFE Workload API and use it to log in to Vault and retrieve the secret.
|
||||
|
||||
.Procedure
|
||||
|
||||
. Run a command inside the running client pod to fetch a JWT-SVID:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc -n $APP_NAMESPACE exec -it $(oc get pod -o=jsonpath='{.items[*].metadata.name}' -l app=$APP_NAME -n $APP_NAMESPACE) \
|
||||
-- /opt/spire/bin/spire-agent api fetch jwt \
|
||||
-socketPath /run/spire/sockets/spire-agent.sock \
|
||||
-audience $AUDIENCE
|
||||
----
|
||||
|
||||
. Copy the token from the output and export it as an environment variable on your local machine:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export IDENTITY_TOKEN=<Your-JWT-Token>
|
||||
----
|
||||
|
||||
. Use `curl` to send the JWT token to the Vault login endpoint to get a Vault client token:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export ROLE="${NAME}-role"
|
||||
$ VAULT_TOKEN=$(curl -s --request POST --data '{ "jwt": "'"${IDENTITY_TOKEN}"'", "role": "'"${ROLE}"'"}' "${VAULT_ADDR}"/v1/auth/jwt/login | jq -r '.auth.client_token')
|
||||
----
|
||||
|
||||
.Verification
|
||||
|
||||
* Use the newly acquired Vault token to read the secret from the KV store:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ curl -s -H "X-Vault-Token: $VAULT_TOKEN" $VAULT_ADDR/v1/secret/$NAME | jq
|
||||
----
|
||||
+
|
||||
You should see the contents of the secret (`"version": "v0.1.0"`) in the output, confirming the entire workflow is successful
|
||||
|
||||
|
||||
@@ -69,14 +69,14 @@ $ helm install vault hashicorp/vault \
|
||||
--values ./vault-helm-value.yaml
|
||||
----
|
||||
|
||||
. Expose the Vault service.
|
||||
. Expose the Vault service by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc expose service vault -n vault
|
||||
----
|
||||
|
||||
. Set the `VAULT_ADDR` environment variable to retrieve the hostname from the new route and then export it.
|
||||
. Set the `VAULT_ADDR` environment variable to retrieve the hostname from the new route and then export it by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
|
||||
25
modules/zero-trust-manager-spiffe-identity-federation.adoc
Normal file
25
modules/zero-trust-manager-spiffe-identity-federation.adoc
Normal file
@@ -0,0 +1,25 @@
|
||||
// Module included in the following assemblies:
|
||||
//
|
||||
// * security/zero_trust_workload_identity_manageer/zero-trust-manager-oidc-federation.adoc
|
||||
|
||||
|
||||
:_mod-docs-content-type: PROCEDURE
|
||||
[id="zero-trust-manager-spiffe-identity-federation_{context}"]
|
||||
= Configuring Azure with the SPIFFE identity federation
|
||||
|
||||
You can configure Azure with the SPIFFE identity federation to enable password-free and automated authentication to the demonstration application.
|
||||
|
||||
.Procedure
|
||||
|
||||
* Federate the identities between the User Managed Identity and the SPIFFE identity associated with the workload application by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ az identity federated-credential create \
|
||||
--name ${NAME} \
|
||||
--identity-name ${USER_ASSIGNED_IDENTITY_NAME} \
|
||||
--resource-group ${RESOURCE_GROUP} \
|
||||
--issuer https://$JWT_ISSUER_ENDPOINT \
|
||||
--subject spiffe://$APP_DOMAIN/ns/$APP_NAMESPACE/sa/$APP_NAME \
|
||||
--audience api://AzureADTokenExchange
|
||||
----
|
||||
135
modules/zero-trust-manager-vault-authenticate-jwt.adoc
Normal file
135
modules/zero-trust-manager-vault-authenticate-jwt.adoc
Normal file
@@ -0,0 +1,135 @@
|
||||
// Module included in the following assemblies:
|
||||
//
|
||||
// * security/zero_trust_workload_identity_manageer/zero-trust-manager-oidc-federation.adoc
|
||||
|
||||
:_mod-docs-content-type: PROCEDURE
|
||||
[id="zero-trust-manager-vault-authenticate-jwt_{context}"]
|
||||
= Configuring JSON Web Token authentication with SPIRE
|
||||
|
||||
You need to set up JSON Web Token (JWT) authentication so your applications can securely log in to Vault by using SPIFFE identities.
|
||||
|
||||
.Prerequisites
|
||||
|
||||
* Make sure that Vault is initialized and unsealed.
|
||||
|
||||
* Ensure that a test secret is stored in the key-value secrets engine.
|
||||
|
||||
.Procedure
|
||||
|
||||
. On your local machine, retrieve the SPIRE Certificate Authority (CA) bundle and save it to a file by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc get cm -n zero-trust-workload-identity-manager spire-bundle -o jsonpath='{ .data.bundle\.crt }' > oidc_provider_ca.pem
|
||||
----
|
||||
|
||||
. Back in the Vault pod shell, create a temporary file and paste the contents of `oidc_provider_ca.pem` into it by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ cat << EOF > /tmp/oidc_provider_ca.pem
|
||||
-----BEGIN CERTIFICATE-----
|
||||
<Paste-Your-Certificate-Content-Here>
|
||||
-----END CERTIFICATE-----
|
||||
EOF
|
||||
----
|
||||
|
||||
. Set up the necessary environment variables for the JWT configuration by running the following commands:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export APP_DOMAIN=<Your-App-Domain>
|
||||
----
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export JWT_ISSUER_ENDPOINT="oidc-discovery.$APP_DOMAIN"
|
||||
----
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export OIDC_URL="https://$JWT_ISSUER_ENDPOINT"
|
||||
----
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export OIDC_CA_PEM="$(cat /tmp/oidc_provider_ca.pem)"
|
||||
----
|
||||
|
||||
. Crate a new environment variable by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export ROLE="${NAME}-role"
|
||||
----
|
||||
|
||||
. Enable the JWT authentication method by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ vault auth enable jwt
|
||||
----
|
||||
|
||||
. Configure you ODIC authentication method by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ vault write auth/jwt/config \
|
||||
oidc_discovery_url=$OIDC_URL \
|
||||
oidc_discovery_ca_pem="$OIDC_CA_PEM" \
|
||||
default_role=$ROLE
|
||||
----
|
||||
|
||||
. Create a policy named `ztwim-policy` by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export POLICY="${NAME}-policy"
|
||||
----
|
||||
|
||||
. Grant read access to the secret you created earlier by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ vault policy write $POLICY -<<EOF
|
||||
path "secret/$NAME" {
|
||||
capabilities = ["read"]
|
||||
}
|
||||
EOF
|
||||
----
|
||||
|
||||
. Create the following environment variables by running the following commands:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export APP_NAME=client
|
||||
----
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export APP_NAMESPACE=demo
|
||||
----
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export AUDIENCE=$APP_NAME
|
||||
----
|
||||
|
||||
. Create a JWT role that binds the policy to workload with a specific SPIFFE ID by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ vault write auth/jwt/role/$ROLE -<<EOF
|
||||
{
|
||||
"role_type": "jwt",
|
||||
"user_claim": "sub",
|
||||
"bound_audiences": "$AUDIENCE",
|
||||
"bound_claims_type": "glob",
|
||||
"bound_claims": {
|
||||
"sub": "spiffe://$APP_DOMAIN/ns/$APP_NAMESPACE/sa/$APP_NAME"
|
||||
},
|
||||
"token_ttl": "24h",
|
||||
"token_policies": "$POLICY"
|
||||
}
|
||||
EOF
|
||||
----
|
||||
54
modules/zero-trust-manager-vault-authenticate-secret.adoc
Normal file
54
modules/zero-trust-manager-vault-authenticate-secret.adoc
Normal file
@@ -0,0 +1,54 @@
|
||||
// Module included in the following assemblies:
|
||||
//
|
||||
// * security/zero_trust_workload_identity_manageer/zero-trust-manager-oidc-federation.adoc
|
||||
|
||||
:_mod-docs-content-type: PROCEDURE
|
||||
[id="zero-trust-manager-vault-authenticate-secret_{context}"]
|
||||
= Authenticating and retrieving the secret
|
||||
|
||||
You use the demonstration application to fetch a JWT token from the SPIFFE Workload API and use it to log in to Vault and retrieve the secret.
|
||||
|
||||
.Procedure
|
||||
|
||||
. Fetch a JWT-SVID by running the following command inside the running client pod:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc -n $APP_NAMESPACE exec -it $(oc get pod -o=jsonpath='{.items[*].metadata.name}' -l app=$APP_NAME -n $APP_NAMESPACE) \
|
||||
-- /opt/spire/bin/spire-agent api fetch jwt \
|
||||
-socketPath /run/spire/sockets/spire-agent.sock \
|
||||
-audience $AUDIENCE
|
||||
----
|
||||
|
||||
. Copy the token from the output and export it as an environment variable on your local machine by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export IDENTITY_TOKEN=<Your-JWT-Token>
|
||||
----
|
||||
|
||||
. Crate a new environment variable by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export ROLE="${NAME}-role"
|
||||
----
|
||||
|
||||
. Use `curl` to send the JWT token to the Vault login endpoint to get a Vault client token by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ VAULT_TOKEN=$(curl -s --request POST --data '{ "jwt": "'"${IDENTITY_TOKEN}"'", "role": "'"${ROLE}"'"}' "${VAULT_ADDR}"/v1/auth/jwt/login | jq -r '.auth.client_token')
|
||||
----
|
||||
|
||||
.Verification
|
||||
|
||||
* Use the newly acquired Vault token to read the secret from the KV store by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ curl -s -H "X-Vault-Token: $VAULT_TOKEN" $VAULT_ADDR/v1/secret/$NAME | jq
|
||||
----
|
||||
+
|
||||
You should see the contents of the secret (`"version": "v0.1.0"`) in the output, confirming the entire workflow is successful
|
||||
|
||||
55
modules/zero-trust-manager-vault-deploy-demo.adoc
Normal file
55
modules/zero-trust-manager-vault-deploy-demo.adoc
Normal file
@@ -0,0 +1,55 @@
|
||||
// Module included in the following assemblies:
|
||||
//
|
||||
// * security/zero_trust_workload_identity_manageer/zero-trust-manager-oidc-federation.adoc
|
||||
|
||||
:_mod-docs-content-type: PROCEDURE
|
||||
[id="zero-trust-manager-vault-deploy-demo_{context}"]
|
||||
|
||||
= Deploying a demonstration application
|
||||
|
||||
When you deploy a demonstration application, you create a simple client application that uses its SPIFFE identity to authenticate with Vault.
|
||||
|
||||
.Procedure
|
||||
|
||||
. On your local machine, set the environment variables for your application by running the following commands:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export APP_NAME=client
|
||||
----
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export APP_NAMESPACE=demo
|
||||
----
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export AUDIENCE=$APP_NAME
|
||||
----
|
||||
|
||||
. Apply the Kubernetes manifest to create the namespace, service account, and deployment for the demo app by running the following command. This deployment mounts the SPIFFE CSI driver socket.
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc apply -f - <<EOF
|
||||
# ... (paste the full YAML from your provided code here) ...
|
||||
EOF
|
||||
----
|
||||
|
||||
.Verification
|
||||
|
||||
* Verify that the client deployment is ready by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc get deploy -n $APP_NAMESPACE
|
||||
----
|
||||
+
|
||||
.Example output
|
||||
[source, terminal]
|
||||
----
|
||||
NAME READY UP-TO-DATE AVAILABLE AGE
|
||||
frontend-app 2/2 2 2 120d
|
||||
backend-api 3/3 3 3 120d
|
||||
----
|
||||
60
modules/zero-trust-manager-vault-enable-kv.adoc
Normal file
60
modules/zero-trust-manager-vault-enable-kv.adoc
Normal file
@@ -0,0 +1,60 @@
|
||||
// Module included in the following assemblies:
|
||||
//
|
||||
// * security/zero_trust_workload_identity_manageer/zero-trust-manager-oidc-federation.adoc
|
||||
|
||||
:_mod-docs-content-type: PROCEDURE
|
||||
[id="zero-trust-manager-vault-enable-kv_{context}"]
|
||||
= Enabling the key-value secrets engine and store a test secret
|
||||
|
||||
You enable the key-value secrets engine to establish a secure, centralized location for managing credentials.
|
||||
|
||||
.Prerequisites
|
||||
|
||||
* Make sure that Vault is initialized and unsealed.
|
||||
|
||||
.Procedure
|
||||
|
||||
. Open another shell session in the `Vault` pod by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc rsh -n vault statefulset/vault
|
||||
----
|
||||
|
||||
. Export your root token again within this new session and log in by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export ROOT_TOKEN=<Your-Root-Token>
|
||||
----
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ vault login "${ROOT_TOKEN}"
|
||||
----
|
||||
|
||||
. Enable the KV secrets engine at the `secret/` path and create a test secret by running the following commands:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export NAME=ztwim
|
||||
----
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ vault secrets enable -path=secret kv
|
||||
----
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ vault kv put secret/$NAME version=v0.1.0
|
||||
----
|
||||
|
||||
.Verification
|
||||
|
||||
* To verify that the secret is stored correctly, run the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ vault kv get secret/$NAME
|
||||
----
|
||||
71
modules/zero-trust-manager-verify-blob-access.adoc
Normal file
71
modules/zero-trust-manager-verify-blob-access.adoc
Normal file
@@ -0,0 +1,71 @@
|
||||
// Module included in the following assemblies:
|
||||
//
|
||||
// * security/zero_trust_workload_identity_manageer/zero-trust-manager-oidc-federation.adoc
|
||||
|
||||
|
||||
:_mod-docs-content-type: PROCEDURE
|
||||
[id="zero-trust-manager-verify-blob-access_{context}"]
|
||||
= Verifying that the application workload can access the content in the Azure Blob Storage
|
||||
|
||||
You can check if the application workload can access the {azure-short} Blob Storage.
|
||||
|
||||
.Prerequisites
|
||||
|
||||
* An Azure Blob Storage has been created.
|
||||
|
||||
.Procedure
|
||||
|
||||
. Retrieve a JWT token from the SPIFFE Workload API by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ oc rsh -n $APP_NAMESPACE deployment/$APP_NAME
|
||||
----
|
||||
|
||||
. Create and export an environment variable named `TOKEN` by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ export TOKEN=$(/opt/app-root/src/get-spiffe-token.py --audience=$AZURE_AUDIENCE)
|
||||
----
|
||||
|
||||
. Log in to {azure-short} CLI included within the pod by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ az login --service-principal \
|
||||
-t ${AZURE_TENANT_ID} \
|
||||
-u ${AZURE_CLIENT_ID} \
|
||||
--federated-token ${TOKEN}
|
||||
----
|
||||
|
||||
. Create a new file with the application workload pod and upload the file to the Blob Storage by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ echo “Hello from OpenShift” > openshift-spire-federated-identities.txt
|
||||
----
|
||||
|
||||
. Upload a file to the {azure-short} Blog Storage by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ az storage blob upload \
|
||||
--account-name ${BLOB_STORE_ACCOUNT} \
|
||||
--container-name ${BLOB_STORE_CONTAINER} \
|
||||
--name openshift-spire-federated-identities.txt \
|
||||
--file openshift-spire-federated-identities.txt \
|
||||
--auth-mode login
|
||||
----
|
||||
|
||||
.Verification
|
||||
* Confirm the file uploaded successfully by listing the files contained by running the following command:
|
||||
+
|
||||
[source,terminal]
|
||||
----
|
||||
$ az storage blob list \
|
||||
--account-name ${BLOB_STORE_ACCOUNT} \
|
||||
--container-name ${BLOB_STORE_CONTAINER} \
|
||||
--auth-mode login \
|
||||
-o table
|
||||
----
|
||||
@@ -1,10 +1,9 @@
|
||||
:_mod-docs-content-type: ASSEMBLY
|
||||
|
||||
|
||||
[id="zero-trust-manager-oidc-federation"]
|
||||
= Zero Trust Workload Identity Manager OIDC federation
|
||||
|
||||
include::_attributes/common-attributes.adoc[]
|
||||
|
||||
:context: zero-trust-manager-oidc-federation
|
||||
|
||||
toc::[]
|
||||
@@ -17,25 +16,61 @@ include::snippets/technology-preview.adoc[]
|
||||
|
||||
The following providers are verified to work with SPIRE OIDC federation:
|
||||
|
||||
* Vault
|
||||
|
||||
* Azure Entra ID
|
||||
|
||||
* Vault
|
||||
|
||||
// About the Entra ID OIDC
|
||||
include::modules/zero-trust-manager-entraid-oidc-about.adoc[leveloffset=+1]
|
||||
|
||||
// configure OIDC route
|
||||
include::modules/zero-trust-manager-create-route-oidc.adoc[leveloffset=+1]
|
||||
include::modules/zero-trust-manager-create-route-oidc.adoc[leveloffset=+2]
|
||||
|
||||
// disable a route
|
||||
include::modules/zero-trust-manager-disabling-route.adoc[leveloffset=+2]
|
||||
|
||||
// configure Azure
|
||||
include::modules/zero-trust-manager-configure-azure.adoc[leveloffset=+1]
|
||||
include::modules/zero-trust-manager-configure-azure.adoc[leveloffset=+2]
|
||||
|
||||
// configure azure blog
|
||||
include::modules/zero-trust-manager-config-azure-blob.adoc[leveloffset=+2]
|
||||
|
||||
// configure azure managed identity
|
||||
include::modules/zero-trust-manager-config-azure-identity.adoc[leveloffset=+2]
|
||||
|
||||
// create demo application
|
||||
include::modules/zero-trust-manager-create-demo-app.adoc[leveloffset=+2]
|
||||
|
||||
// deploy demo application
|
||||
include::modules/zero-trust-manager-deploy-app.adoc[leveloffset=+2]
|
||||
|
||||
// deploy demo application
|
||||
include::modules/zero-trust-manager-spiffe-identity-federation.adoc[leveloffset=+2]
|
||||
|
||||
// verify access to Azure Blob
|
||||
include::modules/zero-trust-manager-verify-blob-access.adoc[leveloffset=+2]
|
||||
|
||||
|
||||
// About the Vault OIDC
|
||||
include::modules/zero-trust-manager-vault-oidc-about.adoc[leveloffset=+1]
|
||||
|
||||
// Install the Vault OIDC
|
||||
include::modules/zero-trust-manager-install-vault-oidc.adoc[leveloffset=+1]
|
||||
include::modules/zero-trust-manager-install-vault-oidc.adoc[leveloffset=+2]
|
||||
|
||||
// Initialize the Vault OIDC
|
||||
include::modules/zero-trust-manager-initialize-vault-oidc.adoc[leveloffset=+1]
|
||||
include::modules/zero-trust-manager-initialize-vault-oidc.adoc[leveloffset=+2]
|
||||
|
||||
// Enable kv secret
|
||||
include::modules/zero-trust-manager-vault-enable-kv.adoc[leveloffset=+2]
|
||||
|
||||
// Authenticate the JWT
|
||||
include::modules/zero-trust-manager-vault-authenticate-jwt.adoc[leveloffset=+2]
|
||||
|
||||
// deploy a demonstration application
|
||||
include::modules/zero-trust-manager-vault-deploy-demo.adoc[leveloffset=+2]
|
||||
|
||||
// authenticate and retrieve secret
|
||||
include::modules/zero-trust-manager-vault-authenticate-secret.adoc[leveloffset=+2]
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user