You can see the reason listed here -> source
TLDR; generate service account key file without transporting the private key.
gcloud iam service-accounts create look-no-keys
export PROJECT_ID=$(gcloud config get-value project)
export CLIENT_EMAIL=look-no-keys@${PROJECT_ID}.iam.gserviceaccount.com
export CLIENT_ID=$(gcloud iam service-accounts \
describe $CLIENT_EMAIL \
--format 'value(uniqueId)')
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member "serviceAccount:$CLIENT_EMAIL" \
--role roles/viewer
export PRIVATE_KEY=$(openssl genrsa 4096)
openssl req -x509 -new \
-key - \
-subj /[email protected] \
-out csr.pem <<< $PRIVATE_KEY
openssl x509 \
-in csr.pem \
-signkey - \
-days 365 \
-out certificate.pem <<< $PRIVATE_KEY
gcloud iam service-accounts keys \
upload certificate.pem \
--iam-account $CLIENT_EMAIL \
--format json > uploaded.json
export PRIVATE_KEY_ID=$(jq -r .name uploaded.json | \
awk -F/ '{print $NF}')
touch look-no-keys.json
chmod 0600 look-no-keys.json
jq -n \
--arg PRIVATE_KEY "${PRIVATE_KEY}" \
--arg PROJECT_ID "${PROJECT_ID}" \
--arg CLIENT_EMAIL "${CLIENT_EMAIL}" \
--arg CLIENT_ID "${CLIENT_ID}" \
--arg PRIVATE_KEY_ID "${PRIVATE_KEY_ID}" \
'{
"type": "service_account",
"project_id": $PROJECT_ID,
"private_key_id": $PRIVATE_KEY_ID,
"private_key": $PRIVATE_KEY,
"client_email": $CLIENT_EMAIL,
"client_id": $CLIENT_ID,
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": @uri "https://www.googleapis.com/robot/v1/metadata/x509/\($CLIENT_EMAIL)"
}' > look-no-keys.json
gcloud auth activate-service-account \
--key-file look-no-keys.json
gcloud compute instances list
# error
gcloud compute instances create demo1