Google announced support for the GCP equivalent of the AWS consolidated bill this Friday. This feature substantially simplifies the complexity of managing billing across multiple projects, allowing you to consolidate the billing and usage statements from all projects into a single bucket.

Attached is a simple Ruby script to allow you to fetch your consolidated bills from a bucket:

#!/usr/bin/env ruby

require 'rubygems'
require 'google/api_client'
require 'json'

if ARGV.size < 7
  puts "gcp_get_bill.rb [project name] [certificate file] [certificate passphrase] [service account] [bucket] [object prefix] [date to fetch]"
  puts "e.g. gcp_get_bill.rb lovey-cache-373 ./my-project.p12 notasecret my-bucket billing 2014-10-13"

project_name = ARGV[0]
certificate_file = ARGV[1]
certificate_passphrase = ARGV[2]
service_account = ARGV[3]
bucket = ARGV[4]
object_prefix = ARGV[5]
fetch_date = Date.parse(ARGV[6])

client =
  :application_name => 'Google Bill Fetcher',
  :application_version => '1.0.0'

storage = client.discovered_api('storage')

key = Google::APIClient::KeyUtils.load_from_pkcs12(certificate_file, certificate_passphrase)
client.authorization =
  :token_credential_uri => '',
  :audience => '',
  :scope => '',
  :issuer => service_account,
  :signing_key => key)

page_token = nil
  response = client.execute(:api_method => storage.objects.list, :parameters => {:project=>project_name, :zone=>'us-central1-a', :bucket=>bucket, :prefix=>object_prefix, :maxResults=>1000, :pageToken=>page_token})
  body = JSON.parse(response.body)
  page_token = body["nextPageToken"] do |obj|
    next unless".csv")

    # Must parse object name to get date since object updated date can be misleading
    updated_at = Date.parse(, 14))
    next if updated_at < fetch_date

    puts "Writing #{} to disk"
    open, 'w' do |io|
      obj_response = client.execute(:api_method => storage.objects.get, :parameters => {:project=>project_name, :zone=>'us-central1-a', :bucket=>bucket, :object=>, :alt=>'media'})
      io.write obj_response.body
end while !page_token.nil?

puts "...complete"