Service accounts can be used to allow limited access control and can be used without the need for the usual web authentication journey that is typically used when authenticating the gcloud SDK. These are ideal for use in a CI setup.
Creating the service account
The steps required to create a service account are outline below, for more information check out the documentation
gcloud iam service-accounts create [SA-NAME] \
--display-name "[SA-DISPLAY-NAME]"
Where SA-NAME
is the name for your service account and SA-DISPLAY-NAME
is a friendly name for the account.
e.g.
gcloud iam service-accounts create jenkins-deployer \
--display-name "Jenkins Deployer Service Account"
List current service accounts
To get a list of current service accounts for the current project:
gcloud iam service-accounts list
We can use this with some additional parameters to to extract the email into an ENV var so that it can be used for later commands. The is used when adding roles to the account
export SA_EMAIL=$(gcloud iam service-accounts list \
--filter="displayName:jenkins-deployer" --format='value(email)')
This sets the value of SA_EMAIL
to be something like [email protected]
.
Get the current project
To set the current project as an ENV var so that it can be used, use the following:
export PROJECT=$(gcloud info —-format=‘value(config.project)’)
Adding roles to the Service Account
Now that the service account has been created, we can assign it roles. The roles you wish to assign depend on what you want to use the service account for. For the purpose of this post we are going to be looking at using the service account to deploy Cloud Functions as well as Firestore security rules.
First add the serviceAccountActor
role.
gcloud projects add-iam-policy-binding $PROJECT —-role roles/iam.serviceAccountActor \
—-member serviceAccount:$SA_EMAIL
There is a beta role that sets the required permissions to deploy cloud functions and firestore database rules, this is roles/firebase.developAdmin
:
gcloud projects add-iam-policy-binding $PROJECT —-role roles/firebase.developAdmin \
—-member serviceAccount:$SA_EMAIL
Generating an access key
To authenticate as the service account we need to generate an access key:
gcloud iam service-accounts keys create jenkins-sa.json —iam-account $SA_EMAIL
This will create a key for the account and download it into jenkins-sa.json
. This file can then be deployed onto your CI server in order to authenticate the Service Account. It is important to secure access to this file as this can be used to authenticate as that account.
Authenticate using the key
In order to authenticate the Service Account to use the gcloud
CLI you need to do the following, where GCP_KEY
is the path to the key created above:
gcloud auth activate-service-account --project=$PROJECT --key-file=$GCP_KEY
Deploying cloud functions
In order to deploy the functions execute the following from the folder that contains the index.js
where the functions are exported.
gcloud beta functions deploy [FUNCTION_NAME] --project $PROJECT --region [REGION]
The region
flag is only required if you are deploying to a region other than the default one.
Scripting the deployment
The following bash script will extract the exported functions and deploy each one:
for FUNCTION_NAME in $(awk '/exports/ {print $1}' index.js | awk -F '.' '{print $2}')
do
echo "About to deploy $FUNCTION_NAME"
gcloud beta functions deploy $FUNCTION_NAME --project $PROJECT --region $REGION
echo "Done deploying $FUNCTION_NAME"
done
It assumes that the PROJECT
, REGION
ENV variables are set.
Firebase CLI
The currently recommend way to authenticate in a CI environment when using the firebase
CLI is to use a token. However, this token has to be for a full user account and can’t be for a service account.
If you wish to use the Firebase CLI to use the service account then all that is required is to set the GOOGLE_APPLICATION_CREDENTIALS
ENV var to the path to the service account access key.
GOOGLE_APPLICATION_CREDENTIALS=jenkins-sa.json
firebase deploy
firebase deploy -P $GCP_PROJECT --only firestore:rules --token "$FIREBASE_TOKEN"