Search code examples
google-compute-enginegoogle-api-dotnet-client

gsutil on a Google Compute Engine VM can't use service account authentication with a key file


I'm launching an instance from the google .net API and despite my best efforts I can't get it to copy anything to or from storage. Currently I'm authenticating with a developer console service account like this:-

string ServiceAccountEmail = "[email protected]";

var certificate = new X509Certificate2(@"key.p12", "notasecret", X509KeyStorageFlags.Exportable);

ServiceAccountCredential credential = new ServiceAccountCredential(
    new ServiceAccountCredential.Initializer(ServiceAccountEmail)
    {
        Scopes = new[] { ComputeService.Scope.Compute, ComputeService.Scope.DevstorageFullControl }
    }.FromCertificate(certificate));

var cs = new ComputeService(new BaseClientService.Initializer
{
    ApplicationName = "appname",
    HttpClientInitializer = (Google.Apis.Http.IConfigurableHttpClientInitializer)credential,
});


Google.Apis.Compute.v1.Data.Instance newinst = new Google.Apis.Compute.v1.Data.Instance();
newinst.Name = "generatedinstance";
newinst.MachineType = "https://www.googleapis.com/compute/v1/projects/projectid/zones/zone/machineTypes/n1-standard-1";

Google.Apis.Compute.v1.Data.AttachedDisk ad = new Google.Apis.Compute.v1.Data.AttachedDisk();
ad.AutoDelete = true;
ad.Boot = true;
ad.Type = "PERSISTENT";
ad.InitializeParams = new Google.Apis.Compute.v1.Data.AttachedDiskInitializeParams();
ad.InitializeParams.DiskName = "newdisk";
ad.InitializeParams.SourceImage = "https://www.googleapis.com/compute/v1/projects/projectid/global/images/customimage";
ad.InitializeParams.DiskType = "https://www.googleapis.com/compute/v1/projects/projectid/zones/zone/diskTypes/pd-standard";
ad.Mode = "READ_WRITE";
newinst.Disks = new List<Google.Apis.Compute.v1.Data.AttachedDisk>();
newinst.Disks.Add(ad);

Google.Apis.Compute.v1.Data.NetworkInterface ni = new Google.Apis.Compute.v1.Data.NetworkInterface();
ni.Network = "https://www.googleapis.com/compute/v1/projects/projectid/global/networks/default";
ni.AccessConfigs = new List<Google.Apis.Compute.v1.Data.AccessConfig>();
ni.AccessConfigs.Add(new Google.Apis.Compute.v1.Data.AccessConfig
{
    Type = "ONE_TO_ONE_NAT",
    Name = "External NAT",
});
newinst.NetworkInterfaces = new List<Google.Apis.Compute.v1.Data.NetworkInterface>();
newinst.NetworkInterfaces.Add(ni);
var start = new Google.Apis.Compute.v1.Data.Metadata.ItemsData();
start.Key = "startup-script";
start.Value = "*startup script* includes gsutil cp which won't work without service account attached";
newinst.Metadata = new Google.Apis.Compute.v1.Data.Metadata();
newinst.Metadata.Kind = "compute#metadata";
newinst.Metadata.Items = new List<Google.Apis.Compute.v1.Data.Metadata.ItemsData>();
newinst.Metadata.Items.Add(start);
newinst.ServiceAccounts = new List<Google.Apis.Compute.v1.Data.ServiceAccount>();

//var sa = new Google.Apis.Compute.v1.Data.ServiceAccount();|with this section
//sa.Email = "[email protected]";      |the instance won't
//sa.Scopes = new[] { ComputeService.Scope.Compute,         |start. (An equivalent
    ComputeService.Scope.DevstorageFullControl };           |is found in instance
//newinst.ServiceAccounts.Add(sa);                          |start REST request)

var instinsert = new InstancesResource.InsertRequest(cs, newinst, "projectid", "zone");
var insertresponse = instinsert.Execute();

The message I get when I try to use gsutil cp is "You do not currently have an active account selected.". Can anyone tell me where I'm going wrong?


Solution

  • OKAY! Problem solved. The part I was getting wrong was the bit commented out in the question-

    var sa = new Google.Apis.Compute.v1.Data.ServiceAccount();
    sa.Email = "[email protected]";
    sa.Scopes = new[] { ComputeService.Scope.Compute,
        ComputeService.Scope.DevstorageFullControl };
    newinst.ServiceAccounts.Add(sa);
    

    I needed the email for the main service account for the developer console in this section rather than the same service account I used to create the credentials but don't ask me why. Point is the instance launches and gsutil is now happily copying away.
    Thanks for your time and help everyone!
    Ross