@@ -19,9 +19,19 @@ set -o pipefail
1919
2020# Install kubectl and kind
2121REPO_ROOT=$( dirname " ${BASH_SOURCE[0]} " ) /..
22+ # shellcheck source=hack/ensure-azcli.sh
23+ source " ${REPO_ROOT} /hack/ensure-azcli.sh"
24+
2225KUBECTL=" ${REPO_ROOT} /hack/tools/bin/kubectl"
2326KIND=" ${REPO_ROOT} /hack/tools/bin/kind"
24- AZWI_ENABLED=${AZWI:- }
27+ AZWI=" ${REPO_ROOT} /hack/tools/bin/azwi"
28+ AZWI_ENABLED=${AZWI_ENABLED:- true}
29+ RAND_SUFFIX=$( openssl rand -hex 4)
30+ export AZWI_STORAGE_ACCOUNT=" oidcissuer${RAND_SUFFIX} "
31+ export AZWI_STORAGE_CONTAINER=" oidc"
32+ export SERVICE_ACCOUNT_ISSUER=${SERVICE_ACCOUNT_ISSUER:- }
33+ export SERVICE_ACCOUNT_SIGNING_PUB_FILEPATH=${SERVICE_ACCOUNT_SIGNING_PUB_FILEPATH:- }
34+ export SERVICE_ACCOUNT_SIGNING_KEY_FILEPATH=${SERVICE_ACCOUNT_SIGNING_KEY_FILEPATH:- }
2535make --directory=" ${REPO_ROOT} " " ${KUBECTL##*/ } " " ${KIND##*/ } "
2636
2737# Export desired cluster name; default is "capz"
4454
4555# To use workload identity, service account signing key pairs base64 encoded should be exposed via the
4656# env variables. The function creates the key pair files after reading it from the env variables.
57+ # TODO we need to document that these env vars are a new requirement
4758function checkAZWIENVPreReqsAndCreateFiles() {
48- if [[ -z " ${SERVICE_ACCOUNT_SIGNING_PUB} " ]]; then
49- echo " 'SERVICE_ACCOUNT_SIGNING_PUB' is not set."
50- exit 1
59+ unset AZURE_STORAGE_KEY
60+ unset AZURE_STORAGE_ACCOUNT
61+ unset SERVICE_ACCOUNT_ISSUER
62+ # check if user is logged into azure cli
63+ if ! az account show > /dev/null 2>&1 ; then
64+ echo " Please login to Azure CLI using 'az login'"
65+ exit 1
5166 fi
5267
53- if [[ -z " ${SERVICE_ACCOUNT_SIGNING_KEY} " ]]; then
54- echo " 'SERVICE_ACCOUNT_SIGNING_KEY' is not set."
55- exit 1
68+ if [ " $( az group exists --name " ${AZWI_RESOURCE_GROUP} " --output tsv) " == ' false' ]; then
69+ echo " Creating resource group '${AZWI_RESOURCE_GROUP} ' in '${AZWI_LOCATION} '"
70+ az group create --name " ${AZWI_RESOURCE_GROUP} " --location " ${AZWI_LOCATION} " --output none --only-show-errors
71+ fi
72+ if ! az storage account show --name " ${AZWI_STORAGE_ACCOUNT} " --resource-group " ${AZWI_RESOURCE_GROUP} " > /dev/null 2>&1 ; then
73+ echo " Creating storage account '${AZWI_STORAGE_ACCOUNT} ' in '${AZWI_RESOURCE_GROUP} '"
74+ az storage account create --resource-group " ${AZWI_RESOURCE_GROUP} " --name " ${AZWI_STORAGE_ACCOUNT} " --allow-blob-public-access true --output none --only-show-errors
75+ fi
76+ if ! az storage container show --name " ${AZWI_STORAGE_CONTAINER} " --account-name " ${AZWI_STORAGE_ACCOUNT} " > /dev/null 2>&1 ; then
77+ echo " Creating storage container '${AZWI_STORAGE_CONTAINER} ' in '${AZWI_STORAGE_ACCOUNT} '"
78+ az storage container create --name " ${AZWI_STORAGE_CONTAINER} " --account-name " ${AZWI_STORAGE_ACCOUNT} " --public-access blob --output none --only-show-errors
5679 fi
57- mkdir -p " $HOME " /azwi/creds
58- echo " ${SERVICE_ACCOUNT_SIGNING_PUB} " > " $HOME " /azwi/creds/sa.pub
59- echo " ${SERVICE_ACCOUNT_SIGNING_KEY} " > " $HOME " /azwi/creds/sa.key
60- SERVICE_ACCOUNT_ISSUER=" ${SERVICE_ACCOUNT_ISSUER:- https:// oidcissuercapzci.blob.core.windows.net/ oidc-capzci/ } "
80+ if [[ -z " ${SERVICE_ACCOUNT_ISSUER} " ]]; then
81+ export SERVICE_ACCOUNT_ISSUER=" https://${AZWI_STORAGE_ACCOUNT} .blob.core.windows.net/${AZWI_STORAGE_CONTAINER} /"
82+ fi
83+ AZWI_OPENID_CONFIG_FILEPATH=" ${REPO_ROOT} /openid-configuration.json"
84+ cat << EOF > $AZWI_OPENID_CONFIG_FILEPATH
85+ {
86+ "issuer": "${SERVICE_ACCOUNT_ISSUER} ",
87+ "jwks_uri": "${SERVICE_ACCOUNT_ISSUER} openid/v1/jwks",
88+ "response_types_supported": [
89+ "id_token"
90+ ],
91+ "subject_types_supported": [
92+ "public"
93+ ],
94+ "id_token_signing_alg_values_supported": [
95+ "RS256"
96+ ]
97+ }
98+ EOF
99+ if [[ -z " ${SERVICE_ACCOUNT_SIGNING_PUB_FILEPATH} " ]]; then
100+ export SERVICE_ACCOUNT_SIGNING_PUB_FILEPATH=" ${REPO_ROOT} /capz-wi-sa.pub"
101+ fi
102+ if [[ -z " ${SERVICE_ACCOUNT_SIGNING_KEY_FILEPATH} " ]]; then
103+ export SERVICE_ACCOUNT_SIGNING_KEY_FILEPATH=" ${REPO_ROOT} /capz-wi-sa.key"
104+ fi
105+ openssl genrsa -help
106+ openssl genrsa -out " ${SERVICE_ACCOUNT_SIGNING_KEY_FILEPATH} " 2048
107+ openssl rsa -help
108+ openssl rsa -in " ${SERVICE_ACCOUNT_SIGNING_KEY_FILEPATH} " -pubout -out " ${SERVICE_ACCOUNT_SIGNING_PUB_FILEPATH} "
109+ AZWI_JWKS_JSON_FILEPATH=" ${REPO_ROOT} /jwks.json"
110+ " ${AZWI} " jwks --public-keys " ${SERVICE_ACCOUNT_SIGNING_PUB_FILEPATH} " --output-file " ${AZWI_JWKS_JSON_FILEPATH} "
111+ echo " Uploading openid-configuration document to '${AZWI_STORAGE_ACCOUNT} ' storage account"
112+ upload_to_blob " ${AZWI_STORAGE_CONTAINER} " " ${AZWI_OPENID_CONFIG_FILEPATH} " " .well-known/openid-configuration"
113+ echo " Uploading jwks document to '${AZWI_STORAGE_ACCOUNT} ' storage account"
114+ upload_to_blob " ${AZWI_STORAGE_CONTAINER} " " ${AZWI_JWKS_JSON_FILEPATH} " " openid/v1/jwks"
115+ az identity create -n " ${USER_IDENTITY} " -g " ${AZWI_RESOURCE_GROUP} " -l " ${AZWI_LOCATION} " --output none --only-show-errors
116+ AZURE_IDENTITY_ID=$( az identity show -n " ${USER_IDENTITY} " -g " ${AZWI_RESOURCE_GROUP} " --query clientId -o tsv)
117+ AZURE_IDENTITY_ID_PRINCIPAL_ID=$( az identity show -n " ${USER_IDENTITY} " -g " ${AZWI_RESOURCE_GROUP} " --query principalId -o tsv)
118+ echo $AZURE_IDENTITY_ID > " ${AZURE_IDENTITY_ID_FILEPATH} "
119+ until az role assignment create --assignee-object-id " ${AZURE_IDENTITY_ID_PRINCIPAL_ID} " --role " Contributor" --scope " /subscriptions/${AZURE_SUBSCRIPTION_ID} " --assignee-principal-type ServicePrincipal --output none --only-show-errors; do
120+ sleep 5
121+ done
122+ az identity federated-credential create -n " capz-federated-identity" \
123+ --identity-name " ${USER_IDENTITY} " \
124+ -g " ${AZWI_RESOURCE_GROUP} " \
125+ --issuer " ${SERVICE_ACCOUNT_ISSUER} " \
126+ --subject " system:serviceaccount:capz-system:capz-manager" --output none --only-show-errors
127+ az identity federated-credential create -n " aso-federated-identity" \
128+ --identity-name " ${USER_IDENTITY} " \
129+ -g " ${AZWI_RESOURCE_GROUP} " \
130+ --issuer " ${SERVICE_ACCOUNT_ISSUER} " \
131+ --subject " system:serviceaccount:capz-system:azureserviceoperator-default" --output none --only-show-errors
132+ }
133+
134+ function upload_to_blob() {
135+ local container_name=$1
136+ local file_path=$2
137+ local blob_name=$3
138+
139+ echo " Uploading ${file_path} to '${AZWI_STORAGE_ACCOUNT} ' storage account"
140+ az storage blob upload \
141+ --container-name " ${container_name} " \
142+ --file " ${file_path} " \
143+ --name " ${blob_name} " \
144+ --account-name " ${AZWI_STORAGE_ACCOUNT} " \
145+ --output none --only-show-errors
61146}
62147
63148# This function create a kind cluster for Workload identity which requires key pairs path
64149# to be mounted on the kind cluster and hence extra mount flags are required.
65150function createKindForAZWI() {
66- echo " creating azwi kind"
151+ echo " creating workload-identity-enabled kind configuration "
67152 cat << EOF | "${KIND} " create cluster --name "${KIND_CLUSTER_NAME} " --config=-
68153 kind: Cluster
69154 apiVersion: kind.x-k8s.io/v1alpha4
70155 nodes:
71156 - role: control-plane
72157 extraMounts:
73- - hostPath: $HOME /azwi/creds/sa.pub
158+ - hostPath: $SERVICE_ACCOUNT_SIGNING_PUB_FILEPATH
74159 containerPath: /etc/kubernetes/pki/sa.pub
75- - hostPath: $HOME /azwi/creds/sa.key
160+ - hostPath: $SERVICE_ACCOUNT_SIGNING_KEY_FILEPATH
76161 containerPath: /etc/kubernetes/pki/sa.key
77162 kubeadmConfigPatches:
78163 - |
@@ -102,11 +187,11 @@ EOF
102187# See: https://github.com/containerd/containerd/blob/main/docs/hosts.md
103188if [ " $AZWI_ENABLED " == ' true' ]
104189 then
105- echo " azwi is enabled..."
190+ echo " workload-identity is enabled..."
106191 checkAZWIENVPreReqsAndCreateFiles
107192 createKindForAZWI
108193else
109- echo " azwi is not enabled..."
194+ echo " workload-identity is not enabled..."
110195 cat << EOF | ${KIND} create cluster --name "${KIND_CLUSTER_NAME} " --config=-
111196kind: Cluster
112197apiVersion: kind.x-k8s.io/v1alpha4
0 commit comments