Google Cloud stores your credentials in a database on your system. These credentials can then be used over and over. Google’s choice of a database means that the CLI and SDK tools can manage a huge number of credentials efficiently. Credentials are managed by configurations.

However, Google also chose not to encrypt the database storing these credentials and I think that this is a potential security weakness and should be reconsidered. IMHO all data should be encrypted. Data that authorizes or protects other data MUST be encrypted.

More details about configurations are in another article that I wrote.

A gcloud configuration is a set of properties that govern the behavior of gcloud and other Google Cloud SDK tools. When you first install gcloud on your desktop a configuration named default is created.

A gcloud configuration is managed by gcloud config configurations. To see the list of configurations on your system:

gcloud config configurations list

This will output a list of configurations present on your system:

NAME      IS_ACTIVE  ACCOUNT                  PROJECT             DEFAULT_ZONE  DEFAULT_REGION
default   True       user1@example.com        default-123456      us-west1-a    us-west1
dev       False      user2@example.com        development-123456  us-east4-c    us-east4
prod      False      user3@example.com        production-123456   us-east4-c    us-east4

The link between a set of configurations and a set of credentials in the database is via the account id.

The databases are stored in the following directory. Replace username with your Windows user name.

C:\Users\username\AppData\Roaming\gcloud

For Linux:

~/.config/gcloud

Credentials are stored in two files: access_tokens.db and credentials.db in this directory. Both of these files are an SQLite database. To see the contents of these databases I wrote two small Python programs.

ACCESS_TOKENS.DB

The database access_tokens.db contains a table named access_tokens with four columns account_id access_token token_expiry rapt_token.

Table schema:

CREATE TABLE IF NOT EXISTS "access_tokens" (account_id TEXT PRIMARY KEY, access_token TEXT, token_expiry TIMESTAMP, rapt_token TEXT);

The column account_id is the email address associated with the credentials.

The access_token is the access token used for authenticating requests, for example in CURL and REST APIs. In another article, I will cover in detail what access tokens and credentials look like and how to use them in your own software. I will also cover how to generate access tokens from credentials.

The token_expiry is the date that the token expires.

The rapt_token is involved with token refresh. I have not yet investigated how to use this.

This Python program will output the contents of the access_tokens.db database.

import sqlite3
import json
import os

# The name of the database to process
filename = 'access_tokens.db'

# Get the user's home directory on Windows
home = os.environ['USERPROFILE']

# Build the full path to the database
path = home + "\\AppData\\Roaming\\gcloud\\" + filename

if os.path.exists(path) is False:
	print('Error: File does not exist')
	print('File:', path)
	exit(1)

conn = sqlite3.connect(path)

cursor = conn.execute('SELECT * FROM access_tokens')

rows = cursor.fetchall()

if len(rows) is 0:
	print('Error: Empty database')
	exit(1)

# Note: This section is not displaying the access_token (row[1]) because it is too long

print('{:30s} {:30s} {}'.format('Account ID', 'Expiration', 'RAPT'))
for row in rows:
	print('{:30s} {:30s} {}'.format(row[0], row[2], row[3]))


print('')
print('########################################')
print('Access Tokens')
print('')

# Code to display the access_token
for row in rows:
	print(row[1])	# access_token

This is the output from the program. I have obfuscated the output to protect the access tokens.

Account ID                     Expiration                     RAPT
user1@example.com              2017-08-15 10:17:10.019000     None
user2@example.com              2018-10-10 06:40:08.479000     None
user3@example.com              2018-10-13 01:47:59.651000     None
user4@example.com              2018-11-02 01:28:59.602000     None

########################################
Access Tokens

ya29.GlyoabcdefghijklmnopqrstuvwxyzUtmlDD7flxUEYyV5fuvHopIoiY7Uq1234567890ABCDEFGHIJKLMNOPQRSTUCWXYZ115ZLli3AAsAEACmdCw4oRNQEYqWnmg
ya29.Glwyabcdefghijklmnopqrstuvwxyzztd68YcGwQOQJc9JwAyMQl9wiTs4Q1234567890ABCDEFGHIJKLMNOPQRSTUCWXYZzoBVg66jxYqsmuTUZqYLGpz36zuKHrw
ya29.Glw1abcdefghijklmnopqrstuvwxyzaus_auVkXDGjTSsqI7d3Q_qY2MfKgi1234567890ABCDEFGHIJKLMNOPQRSTUCWXYZpbsuDDDVG588MOHI0FkZZTrVT55CeQ
ya29.GlxabcdefghijklmnopqrstuvwxyzMVGfDl8mjs19_ci3rGVsxfzuIWo_HxoC1234567890ABCDEFGHIJKLMNOPQRSTUCWXYZAfpuNHHEHB9jRKmifxJ2MwMq7ddZA
CREDENTIALS.DB

The database credentials.db contains a table named credentials with two columns account_id value.

Table schema:

CREATE TABLE IF NOT EXISTS "credentials" (account_id TEXT PRIMARY KEY, value BLOB);

The column account_id is the email address associated with the credentials.

The column value is your credentials in Json format. I will cover the format of credentials in detail in another article.

This Python program will output the contents of the credentials.db database.

import sqlite3
import json
import os

# The name of the database to process
filename = 'credentials.db'

# Get the user's home directory on Windows
home = os.environ['USERPROFILE']

# Build the full path to the database
path = home + "\\AppData\\Roaming\\gcloud\\" + filename

if os.path.exists(path) is False:
	print('Error: File does not exist')
	print('File:', path)
	exit(1)

conn = sqlite3.connect(path)

cursor = conn.execute('SELECT * FROM credentials')

rows = cursor.fetchall()

if len(rows) is 0:
	print('Error: Empty database')
	exit(1)

# Note: This section is not displaying the value (row[1]) because it is too long

print('Account ID')
for row in rows:
	print('{}'.format(row[0]))


print('')
print('########################################')
print('Credentials')
print('')

# Code to display the credential
for row in rows:
	print(row[1])	# value

This is the output from the program. I have obfuscated the output to protect the credentials by deleting them from the listing.

Account ID
user1@example.com
user2@example.com
user3@example.com
user4@example.com

########################################
Credentials

<Contents deleted for this article for security reasons>

There you have it. Details on where Google stores credentials on your system, the format of the database and what the credentials look like on your system.