From 46822aea2c4f4f3b944f3dc98756bff95621f816 Mon Sep 17 00:00:00 2001 From: Joshua Wong Date: Thu, 3 Oct 2019 15:45:18 -0500 Subject: [PATCH] Add support for GKE Workload Identity (#1810) * Allow the velero server to be created on GCP even without a provided service account key in order to support workload identity and default compute engine credentials. Add option for adding service account annotations. Signed-off-by: Joshua Wong --- Gopkg.lock | 4 +- pkg/cloudprovider/gcp/object_store.go | 103 +- pkg/cloudprovider/gcp/volume_snapshotter.go | 41 +- pkg/cmd/cli/install/install.go | 30 +- pkg/install/deployment.go | 1 + pkg/install/resources.go | 10 +- pkg/install/resources_test.go | 3 +- .../master/api-types/backupstoragelocation.md | 1 + site/docs/master/gcp-config.md | 24 + .../iamcredentials/v1/iamcredentials-gen.go | 1056 +++++++++++++++++ 10 files changed, 1193 insertions(+), 80 deletions(-) create mode 100644 vendor/google.golang.org/api/iamcredentials/v1/iamcredentials-gen.go diff --git a/Gopkg.lock b/Gopkg.lock index e791eb90e..9c5f78459 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -584,7 +584,7 @@ revision = "26559e0f760e39c24d730d3224364aef164ee23f" [[projects]] - digest = "1:352a8b8a41fd11320b8b2327a4c2c8f6967578a2d54886b64748c0a46d4a8b5e" + digest = "1:98ef43d760c0123cf289071e1043176178c60205902a60beba99bb9f988fdcf9" name = "google.golang.org/api" packages = [ "compute/v1", @@ -592,6 +592,7 @@ "googleapi", "googleapi/internal/uritemplates", "googleapi/transport", + "iamcredentials/v1", "internal", "iterator", "option", @@ -1102,6 +1103,7 @@ "golang.org/x/oauth2/google", "google.golang.org/api/compute/v1", "google.golang.org/api/googleapi", + "google.golang.org/api/iamcredentials/v1", "google.golang.org/api/iterator", "google.golang.org/api/option", "google.golang.org/grpc", diff --git a/pkg/cloudprovider/gcp/object_store.go b/pkg/cloudprovider/gcp/object_store.go index 4381d357c..1ff5330e0 100644 --- a/pkg/cloudprovider/gcp/object_store.go +++ b/pkg/cloudprovider/gcp/object_store.go @@ -18,15 +18,15 @@ package gcp import ( "context" + "encoding/base64" "io" - "io/ioutil" - "os" "time" "cloud.google.com/go/storage" "github.com/pkg/errors" "github.com/sirupsen/logrus" "golang.org/x/oauth2/google" + "google.golang.org/api/iamcredentials/v1" "google.golang.org/api/iterator" "google.golang.org/api/option" @@ -34,8 +34,9 @@ import ( ) const ( - credentialsEnvVar = "GOOGLE_APPLICATION_CREDENTIALS" - kmsKeyNameConfigKey = "kmsKeyName" + credentialsEnvVar = "GOOGLE_APPLICATION_CREDENTIALS" + kmsKeyNameConfigKey = "kmsKeyName" + serviceAccountConfig = "serviceAccount" ) // bucketWriter wraps the GCP SDK functions for accessing object store so they can be faked for testing. @@ -67,6 +68,7 @@ type ObjectStore struct { googleAccessID string privateKey []byte bucketWriter bucketWriter + iamSvc *iamcredentials.Service } func NewObjectStore(logger logrus.FieldLogger) *ObjectStore { @@ -74,35 +76,30 @@ func NewObjectStore(logger logrus.FieldLogger) *ObjectStore { } func (o *ObjectStore) Init(config map[string]string) error { - if err := cloudprovider.ValidateObjectStoreConfigKeys(config, kmsKeyNameConfigKey); err != nil { + if err := cloudprovider.ValidateObjectStoreConfigKeys(config, kmsKeyNameConfigKey, serviceAccountConfig); err != nil { return err } + // Find default token source to extract the GoogleAccessID + ctx := context.Background() + creds, err := google.FindDefaultCredentials(ctx) - credentialsFile := os.Getenv(credentialsEnvVar) - if credentialsFile == "" { - return errors.Errorf("%s is undefined", credentialsEnvVar) - } - - // Get the email and private key from the credentials file so we can pre-sign download URLs - creds, err := ioutil.ReadFile(credentialsFile) if err != nil { return errors.WithStack(err) } - jwtConfig, err := google.JWTConfigFromJSON(creds) + + if creds.JSON != nil { + // Using Credentials File + err = o.initFromKeyFile(creds) + } else { + // Using compute engine credentials. Use this if workload identity is enabled. + err = o.initFromComputeEngine(config) + } + if err != nil { - return errors.Wrap(err, "error parsing credentials file; should be JSON") - } - if jwtConfig.Email == "" { - return errors.Errorf("credentials file pointed to by %s does not contain an email", credentialsEnvVar) - } - if len(jwtConfig.PrivateKey) == 0 { - return errors.Errorf("credentials file pointed to by %s does not contain a private key", credentialsEnvVar) + return errors.WithStack(err) } - o.googleAccessID = jwtConfig.Email - o.privateKey = jwtConfig.PrivateKey - - client, err := storage.NewClient(context.Background(), option.WithScopes(storage.ScopeReadWrite)) + client, err := storage.NewClient(ctx, option.WithScopes(storage.ScopeReadWrite)) if err != nil { return errors.WithStack(err) } @@ -112,10 +109,37 @@ func (o *ObjectStore) Init(config map[string]string) error { client: o.client, kmsKeyName: config[kmsKeyNameConfigKey], } - return nil } +func (o *ObjectStore) initFromKeyFile(creds *google.Credentials) error { + jwtConfig, err := google.JWTConfigFromJSON(creds.JSON) + if err != nil { + return errors.Wrap(err, "error parsing credentials file; should be JSON") + } + if jwtConfig.Email == "" { + return errors.Errorf("credentials file pointed to by %s does not contain an email", "GOOGLE_APPLICATION_CREDENTIALS") + } + if len(jwtConfig.PrivateKey) == 0 { + return errors.Errorf("credentials file pointed to by %s does not contain a private key", "GOOGLE_APPLICATION_CREDENTIALS") + } + + o.googleAccessID = jwtConfig.Email + o.privateKey = jwtConfig.PrivateKey + return nil +} + +func (o *ObjectStore) initFromComputeEngine(config map[string]string) error { + var err error + var ok bool + o.googleAccessID, ok = config["serviceAccount"] + if !ok { + return errors.Errorf("serviceAccount is expected to be provided as an item in BackupStorageLocation's config") + } + o.iamSvc, err = iamcredentials.NewService(context.Background()) + return err +} + func (o *ObjectStore) PutObject(bucket, key string, body io.Reader) error { w := o.bucketWriter.getWriteCloser(bucket, key) @@ -204,11 +228,34 @@ func (o *ObjectStore) DeleteObject(bucket, key string) error { return errors.Wrapf(o.client.Bucket(bucket).Object(key).Delete(context.Background()), "error deleting object %s", key) } +/* + * Use the iamSignBlob api call to sign the url if there is no credentials file to get the key from. + * https://cloud.google.com/iam/credentials/reference/rest/v1/projects.serviceAccounts/signBlob + */ +func (o *ObjectStore) SignBytes(bytes []byte) ([]byte, error) { + name := "projects/-/serviceAccounts/" + o.googleAccessID + resp, err := o.iamSvc.Projects.ServiceAccounts.SignBlob(name, &iamcredentials.SignBlobRequest{ + Payload: base64.StdEncoding.EncodeToString(bytes), + }).Context(context.Background()).Do() + + if err != nil { + return nil, err + } + return base64.StdEncoding.DecodeString(resp.SignedBlob) +} + func (o *ObjectStore) CreateSignedURL(bucket, key string, ttl time.Duration) (string, error) { - return storage.SignedURL(bucket, key, &storage.SignedURLOptions{ + options := storage.SignedURLOptions{ GoogleAccessID: o.googleAccessID, - PrivateKey: o.privateKey, Method: "GET", Expires: time.Now().Add(ttl), - }) + } + + if o.privateKey == nil { + options.SignBytes = o.SignBytes + } else { + options.PrivateKey = o.privateKey + } + + return storage.SignedURL(bucket, key, &options) } diff --git a/pkg/cloudprovider/gcp/volume_snapshotter.go b/pkg/cloudprovider/gcp/volume_snapshotter.go index 4bf6ae366..88b34cbdb 100644 --- a/pkg/cloudprovider/gcp/volume_snapshotter.go +++ b/pkg/cloudprovider/gcp/volume_snapshotter.go @@ -18,9 +18,7 @@ package gcp import ( "encoding/json" - "io/ioutil" "net/http" - "os" "strings" "github.com/pkg/errors" @@ -60,13 +58,14 @@ func (b *VolumeSnapshotter) Init(config map[string]string) error { return err } + /* Works with both credential files and the default compute engine service account */ + creds, err := google.FindDefaultCredentials(oauth2.NoContext, compute.ComputeScope) + if err != nil { + return errors.WithStack(err) + } b.snapshotLocation = config[snapshotLocationKey] - project, err := extractProjectFromCreds() - if err != nil { - return err - } - b.volumeProject = project + b.volumeProject = creds.ProjectID // get snapshot project from 'project' config key if specified, // otherwise from the credentials file @@ -74,11 +73,7 @@ func (b *VolumeSnapshotter) Init(config map[string]string) error { if b.snapshotProject == "" { b.snapshotProject = b.volumeProject } - - client, err := google.DefaultClient(oauth2.NoContext, compute.ComputeScope) - if err != nil { - return errors.WithStack(err) - } + client := oauth2.NewClient(oauth2.NoContext, creds.TokenSource) gce, err := compute.New(client) if err != nil { @@ -90,28 +85,6 @@ func (b *VolumeSnapshotter) Init(config map[string]string) error { return nil } -func extractProjectFromCreds() (string, error) { - credsBytes, err := ioutil.ReadFile(os.Getenv("GOOGLE_APPLICATION_CREDENTIALS")) - if err != nil { - return "", errors.WithStack(err) - } - - type credentials struct { - ProjectID string `json:"project_id"` - } - - var creds credentials - if err := json.Unmarshal(credsBytes, &creds); err != nil { - return "", errors.WithStack(err) - } - - if creds.ProjectID == "" { - return "", errors.New("cannot fetch project_id from GCP credentials file") - } - - return creds.ProjectID, nil -} - // isMultiZone returns true if the failure-domain tag contains // double underscore, which is the separator used // by GKE when a storage class spans multiple availablity diff --git a/pkg/cmd/cli/install/install.go b/pkg/cmd/cli/install/install.go index f62584356..79b70fa2b 100644 --- a/pkg/cmd/cli/install/install.go +++ b/pkg/cmd/cli/install/install.go @@ -45,6 +45,7 @@ type InstallOptions struct { Prefix string ProviderName string PodAnnotations flag.Map + ServiceAccountAnnotations flag.Map VeleroPodCPURequest string VeleroPodMemRequest string VeleroPodCPULimit string @@ -74,6 +75,7 @@ func (o *InstallOptions) BindFlags(flags *pflag.FlagSet) { flags.StringVar(&o.Image, "image", o.Image, "image to use for the Velero and restic server pods. Optional.") flags.StringVar(&o.Prefix, "prefix", o.Prefix, "prefix under which all Velero data should be stored within the bucket. Optional.") flags.Var(&o.PodAnnotations, "pod-annotations", "annotations to add to the Velero and restic pods. Optional. Format is key1=value1,key2=value2") + flags.Var(&o.ServiceAccountAnnotations, "sa-annotations", "annotations to add to the Velero ServiceAccount. Add iam.gke.io/gcp-service-account=[GSA_NAME]@[PROJECT_NAME].iam.gserviceaccount.com for workload identity. Optional. Format is key1=value1,key2=value2") flags.StringVar(&o.VeleroPodCPURequest, "velero-pod-cpu-request", o.VeleroPodCPURequest, `CPU request for Velero pod. A value of "0" is treated as unbounded. Optional.`) flags.StringVar(&o.VeleroPodMemRequest, "velero-pod-mem-request", o.VeleroPodMemRequest, `memory request for Velero pod. A value of "0" is treated as unbounded. Optional.`) flags.StringVar(&o.VeleroPodCPULimit, "velero-pod-cpu-limit", o.VeleroPodCPULimit, `CPU limit for Velero pod. A value of "0" is treated as unbounded. Optional.`) @@ -95,19 +97,20 @@ func (o *InstallOptions) BindFlags(flags *pflag.FlagSet) { // NewInstallOptions instantiates a new, default InstallOptions struct. func NewInstallOptions() *InstallOptions { return &InstallOptions{ - Namespace: velerov1api.DefaultNamespace, - Image: install.DefaultImage, - BackupStorageConfig: flag.NewMap(), - VolumeSnapshotConfig: flag.NewMap(), - PodAnnotations: flag.NewMap(), - VeleroPodCPURequest: install.DefaultVeleroPodCPURequest, - VeleroPodMemRequest: install.DefaultVeleroPodMemRequest, - VeleroPodCPULimit: install.DefaultVeleroPodCPULimit, - VeleroPodMemLimit: install.DefaultVeleroPodMemLimit, - ResticPodCPURequest: install.DefaultResticPodCPURequest, - ResticPodMemRequest: install.DefaultResticPodMemRequest, - ResticPodCPULimit: install.DefaultResticPodCPULimit, - ResticPodMemLimit: install.DefaultResticPodMemLimit, + Namespace: velerov1api.DefaultNamespace, + Image: install.DefaultImage, + BackupStorageConfig: flag.NewMap(), + VolumeSnapshotConfig: flag.NewMap(), + PodAnnotations: flag.NewMap(), + ServiceAccountAnnotations: flag.NewMap(), + VeleroPodCPURequest: install.DefaultVeleroPodCPURequest, + VeleroPodMemRequest: install.DefaultVeleroPodMemRequest, + VeleroPodCPULimit: install.DefaultVeleroPodCPULimit, + VeleroPodMemLimit: install.DefaultVeleroPodMemLimit, + ResticPodCPURequest: install.DefaultResticPodCPURequest, + ResticPodMemRequest: install.DefaultResticPodMemRequest, + ResticPodCPULimit: install.DefaultResticPodCPULimit, + ResticPodMemLimit: install.DefaultResticPodMemLimit, // Default to creating a VSL unless we're told otherwise UseVolumeSnapshots: true, } @@ -142,6 +145,7 @@ func (o *InstallOptions) AsVeleroOptions() (*install.VeleroOptions, error) { Bucket: o.BucketName, Prefix: o.Prefix, PodAnnotations: o.PodAnnotations.Data(), + ServiceAccountAnnotations: o.ServiceAccountAnnotations.Data(), VeleroPodResources: veleroPodResources, ResticPodResources: resticPodResources, SecretData: secretData, diff --git a/pkg/install/deployment.go b/pkg/install/deployment.go index 4f8686ecf..168653a1d 100644 --- a/pkg/install/deployment.go +++ b/pkg/install/deployment.go @@ -69,6 +69,7 @@ func WithEnvFromSecretKey(varName, secret, key string) podTemplateOption { func WithSecret(secretPresent bool) podTemplateOption { return func(c *podTemplateConfig) { c.withSecret = secretPresent + } } diff --git a/pkg/install/resources.go b/pkg/install/resources.go index 81b036ae7..05ccc00ac 100644 --- a/pkg/install/resources.go +++ b/pkg/install/resources.go @@ -91,9 +91,11 @@ func objectMeta(namespace, name string) metav1.ObjectMeta { } } -func ServiceAccount(namespace string) *corev1.ServiceAccount { +func ServiceAccount(namespace string, annotations map[string]string) *corev1.ServiceAccount { + objMeta := objectMeta(namespace, "velero") + objMeta.Annotations = annotations return &corev1.ServiceAccount{ - ObjectMeta: objectMeta(namespace, "velero"), + ObjectMeta: objMeta, TypeMeta: metav1.TypeMeta{ Kind: "ServiceAccount", APIVersion: corev1.SchemeGroupVersion.String(), @@ -185,6 +187,7 @@ func Secret(namespace string, data []byte) *corev1.Secret { func appendUnstructured(list *unstructured.UnstructuredList, obj runtime.Object) error { u, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&obj) + // Remove the status field so we're not sending blank data to the server. // On CRDs, having an empty status is actually a validation error. delete(u, "status") @@ -202,6 +205,7 @@ type VeleroOptions struct { Bucket string Prefix string PodAnnotations map[string]string + ServiceAccountAnnotations map[string]string VeleroPodResources corev1.ResourceRequirements ResticPodResources corev1.ResourceRequirements SecretData []byte @@ -231,7 +235,7 @@ func AllResources(o *VeleroOptions) (*unstructured.UnstructuredList, error) { crb := ClusterRoleBinding(o.Namespace) appendUnstructured(resources, crb) - sa := ServiceAccount(o.Namespace) + sa := ServiceAccount(o.Namespace, o.ServiceAccountAnnotations) appendUnstructured(resources, sa) if o.SecretData != nil { diff --git a/pkg/install/resources_test.go b/pkg/install/resources_test.go index 84818dfbb..5aa240e81 100644 --- a/pkg/install/resources_test.go +++ b/pkg/install/resources_test.go @@ -45,6 +45,7 @@ func TestResources(t *testing.T) { assert.Equal(t, "", crb.ObjectMeta.Namespace) assert.Equal(t, "velero", crb.Subjects[0].Namespace) - sa := ServiceAccount("velero") + sa := ServiceAccount("velero", map[string]string{"abcd": "cbd"}) assert.Equal(t, "velero", sa.ObjectMeta.Namespace) + assert.Equal(t, "cbd", sa.ObjectMeta.Annotations["abcd"]) } diff --git a/site/docs/master/api-types/backupstoragelocation.md b/site/docs/master/api-types/backupstoragelocation.md index 4e907ca20..0e46fc245 100644 --- a/site/docs/master/api-types/backupstoragelocation.md +++ b/site/docs/master/api-types/backupstoragelocation.md @@ -71,6 +71,7 @@ The configurable parameters are as follows: | Key | Type | Default | Meaning | | --- | --- | --- | --- | | `kmsKeyName` | string | Empty | Name of the Cloud KMS key to use to encrypt backups stored in this location, in the form `projects/P/locations/L/keyRings/R/cryptoKeys/K`. See [customer-managed Cloud KMS keys](https://cloud.google.com/storage/docs/encryption/using-customer-managed-keys) for details. | +| `serviceAccount` | string | Empty | Name of the GCP service account to use for this backup storage location. Specify the service account here if you want to use workload identity instead of providing the key file. [0]: #aws [1]: #gcp diff --git a/site/docs/master/gcp-config.md b/site/docs/master/gcp-config.md index b578f7323..2795ab41b 100644 --- a/site/docs/master/gcp-config.md +++ b/site/docs/master/gcp-config.md @@ -136,6 +136,29 @@ Additionally, you can specify `--use-restic` to enable restic support, and `--wa For more complex installation needs, use either the Helm chart, or add `--dry-run -o yaml` options for generating the YAML representation for the installation. +## Using Workload Identity (Optional) + +If you are running Velero on a GKE cluster with workload identity enabled, you may want to bind Velero's Kubernetes service account to a GCP service account with the appropriate permissions instead of providing the key file during installation. + +To do this, you must grant the GCP service account(the one you created in Step 3) the 'iam.serviceAccounts.signBlob' role. This is so that Velero's Kubernetes service account can create signed urls for the GCP bucket. + +Next, add an IAM policy binding to grant Velero's Kubernetes service account access to your created GCP service account. + +```bash +gcloud iam service-accounts add-iam-policy-binding \ + --role roles/iam.workloadIdentityUser \ + --member serviceAccount:[PROJECT_ID].svc.id.goog[velero/velero] \ + [GSA_NAME]@[PROJECT_ID].iam.gserviceaccount.com +``` + +For more information on configuring workload identity on GKE, look at the [official GCP documentation][24] for more details. + +Finally, you must add a service account annotation to the Kubernetes service account so that it will know which GCP service account to use. You can do this during installation with `--sa-annotations`. Furthermore, you must also use the flag `--no-secret` so that Velero will know not to look for a key file. You must also add the GCP service account name in `--backup-location-config`. + +```bash +velero install --provider gcp --no-secret --sa-annotations iam.gke.io/gcp-service-account=[GSA_NAME]@[PROJECT_ID].iam.gserviceaccount.com --backup-location-config serviceAccount=[GSA_NAME]@[PROJECT_ID].iam.gserviceaccount.com +``` + [0]: namespace.md [7]: api-types/backupstoragelocation.md#gcp [8]: api-types/volumesnapshotlocation.md#gcp @@ -144,3 +167,4 @@ For more complex installation needs, use either the Helm chart, or add `--dry-ru [20]: faq.md [22]: https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control#iam-rolebinding-bootstrap [23]: install-overview.md#velero-resource-requirements +[24]: https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity diff --git a/vendor/google.golang.org/api/iamcredentials/v1/iamcredentials-gen.go b/vendor/google.golang.org/api/iamcredentials/v1/iamcredentials-gen.go new file mode 100644 index 000000000..ca462d113 --- /dev/null +++ b/vendor/google.golang.org/api/iamcredentials/v1/iamcredentials-gen.go @@ -0,0 +1,1056 @@ +// Copyright 2019 Google LLC. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated file. DO NOT EDIT. + +// Package iamcredentials provides access to the IAM Service Account Credentials API. +// +// For product documentation, see: https://cloud.google.com/iam/docs/creating-short-lived-service-account-credentials +// +// Creating a client +// +// Usage example: +// +// import "google.golang.org/api/iamcredentials/v1" +// ... +// ctx := context.Background() +// iamcredentialsService, err := iamcredentials.NewService(ctx) +// +// In this example, Google Application Default Credentials are used for authentication. +// +// For information on how to create and obtain Application Default Credentials, see https://developers.google.com/identity/protocols/application-default-credentials. +// +// Other authentication options +// +// To use an API key for authentication (note: some APIs do not support API keys), use option.WithAPIKey: +// +// iamcredentialsService, err := iamcredentials.NewService(ctx, option.WithAPIKey("AIza...")) +// +// To use an OAuth token (e.g., a user token obtained via a three-legged OAuth flow), use option.WithTokenSource: +// +// config := &oauth2.Config{...} +// // ... +// token, err := config.Exchange(ctx, ...) +// iamcredentialsService, err := iamcredentials.NewService(ctx, option.WithTokenSource(config.TokenSource(ctx, token))) +// +// See https://godoc.org/google.golang.org/api/option/ for details on options. +package iamcredentials // import "google.golang.org/api/iamcredentials/v1" + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "net/url" + "strconv" + "strings" + + gensupport "google.golang.org/api/gensupport" + googleapi "google.golang.org/api/googleapi" + option "google.golang.org/api/option" + htransport "google.golang.org/api/transport/http" +) + +// Always reference these packages, just in case the auto-generated code +// below doesn't. +var _ = bytes.NewBuffer +var _ = strconv.Itoa +var _ = fmt.Sprintf +var _ = json.NewDecoder +var _ = io.Copy +var _ = url.Parse +var _ = gensupport.MarshalJSON +var _ = googleapi.Version +var _ = errors.New +var _ = strings.Replace +var _ = context.Canceled + +const apiId = "iamcredentials:v1" +const apiName = "iamcredentials" +const apiVersion = "v1" +const basePath = "https://iamcredentials.googleapis.com/" + +// OAuth2 scopes used by this API. +const ( + // View and manage your data across Google Cloud Platform services + CloudPlatformScope = "https://www.googleapis.com/auth/cloud-platform" +) + +// NewService creates a new Service. +func NewService(ctx context.Context, opts ...option.ClientOption) (*Service, error) { + scopesOption := option.WithScopes( + "https://www.googleapis.com/auth/cloud-platform", + ) + // NOTE: prepend, so we don't override user-specified scopes. + opts = append([]option.ClientOption{scopesOption}, opts...) + client, endpoint, err := htransport.NewClient(ctx, opts...) + if err != nil { + return nil, err + } + s, err := New(client) + if err != nil { + return nil, err + } + if endpoint != "" { + s.BasePath = endpoint + } + return s, nil +} + +// New creates a new Service. It uses the provided http.Client for requests. +// +// Deprecated: please use NewService instead. +// To provide a custom HTTP client, use option.WithHTTPClient. +// If you are using google.golang.org/api/googleapis/transport.APIKey, use option.WithAPIKey with NewService instead. +func New(client *http.Client) (*Service, error) { + if client == nil { + return nil, errors.New("client is nil") + } + s := &Service{client: client, BasePath: basePath} + s.Projects = NewProjectsService(s) + return s, nil +} + +type Service struct { + client *http.Client + BasePath string // API endpoint base URL + UserAgent string // optional additional User-Agent fragment + + Projects *ProjectsService +} + +func (s *Service) userAgent() string { + if s.UserAgent == "" { + return googleapi.UserAgent + } + return googleapi.UserAgent + " " + s.UserAgent +} + +func NewProjectsService(s *Service) *ProjectsService { + rs := &ProjectsService{s: s} + rs.ServiceAccounts = NewProjectsServiceAccountsService(s) + return rs +} + +type ProjectsService struct { + s *Service + + ServiceAccounts *ProjectsServiceAccountsService +} + +func NewProjectsServiceAccountsService(s *Service) *ProjectsServiceAccountsService { + rs := &ProjectsServiceAccountsService{s: s} + return rs +} + +type ProjectsServiceAccountsService struct { + s *Service +} + +type GenerateAccessTokenRequest struct { + // Delegates: The sequence of service accounts in a delegation chain. + // Each service + // account must be granted the `roles/iam.serviceAccountTokenCreator` + // role + // on its next service account in the chain. The last service account in + // the + // chain must be granted the `roles/iam.serviceAccountTokenCreator` + // role + // on the service account that is specified in the `name` field of + // the + // request. + // + // The delegates must have the following + // format: + // `projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`. The `-` + // wildcard + // character is required; replacing it with a project ID is invalid. + Delegates []string `json:"delegates,omitempty"` + + // Lifetime: The desired lifetime duration of the access token in + // seconds. + // Must be set to a value less than or equal to 3600 (1 hour). If a + // value is + // not specified, the token's lifetime will be set to a default value of + // one + // hour. + Lifetime string `json:"lifetime,omitempty"` + + // Scope: Code to identify the scopes to be included in the OAuth 2.0 + // access token. + // See https://developers.google.com/identity/protocols/googlescopes for + // more + // information. + // At least one value required. + Scope []string `json:"scope,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Delegates") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Delegates") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *GenerateAccessTokenRequest) MarshalJSON() ([]byte, error) { + type NoMethod GenerateAccessTokenRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type GenerateAccessTokenResponse struct { + // AccessToken: The OAuth 2.0 access token. + AccessToken string `json:"accessToken,omitempty"` + + // ExpireTime: Token expiration time. + // The expiration time is always set. + ExpireTime string `json:"expireTime,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "AccessToken") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "AccessToken") to include + // in API requests with the JSON null value. By default, fields with + // empty values are omitted from API requests. However, any field with + // an empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *GenerateAccessTokenResponse) MarshalJSON() ([]byte, error) { + type NoMethod GenerateAccessTokenResponse + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type GenerateIdTokenRequest struct { + // Audience: The audience for the token, such as the API or account that + // this token + // grants access to. + Audience string `json:"audience,omitempty"` + + // Delegates: The sequence of service accounts in a delegation chain. + // Each service + // account must be granted the `roles/iam.serviceAccountTokenCreator` + // role + // on its next service account in the chain. The last service account in + // the + // chain must be granted the `roles/iam.serviceAccountTokenCreator` + // role + // on the service account that is specified in the `name` field of + // the + // request. + // + // The delegates must have the following + // format: + // `projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`. The `-` + // wildcard + // character is required; replacing it with a project ID is invalid. + Delegates []string `json:"delegates,omitempty"` + + // IncludeEmail: Include the service account email in the token. If set + // to `true`, the + // token will contain `email` and `email_verified` claims. + IncludeEmail bool `json:"includeEmail,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Audience") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Audience") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *GenerateIdTokenRequest) MarshalJSON() ([]byte, error) { + type NoMethod GenerateIdTokenRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type GenerateIdTokenResponse struct { + // Token: The OpenId Connect ID token. + Token string `json:"token,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "Token") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Token") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *GenerateIdTokenResponse) MarshalJSON() ([]byte, error) { + type NoMethod GenerateIdTokenResponse + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type SignBlobRequest struct { + // Delegates: The sequence of service accounts in a delegation chain. + // Each service + // account must be granted the `roles/iam.serviceAccountTokenCreator` + // role + // on its next service account in the chain. The last service account in + // the + // chain must be granted the `roles/iam.serviceAccountTokenCreator` + // role + // on the service account that is specified in the `name` field of + // the + // request. + // + // The delegates must have the following + // format: + // `projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`. The `-` + // wildcard + // character is required; replacing it with a project ID is invalid. + Delegates []string `json:"delegates,omitempty"` + + // Payload: The bytes to sign. + Payload string `json:"payload,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Delegates") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Delegates") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SignBlobRequest) MarshalJSON() ([]byte, error) { + type NoMethod SignBlobRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type SignBlobResponse struct { + // KeyId: The ID of the key used to sign the blob. + KeyId string `json:"keyId,omitempty"` + + // SignedBlob: The signed blob. + SignedBlob string `json:"signedBlob,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "KeyId") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "KeyId") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SignBlobResponse) MarshalJSON() ([]byte, error) { + type NoMethod SignBlobResponse + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type SignJwtRequest struct { + // Delegates: The sequence of service accounts in a delegation chain. + // Each service + // account must be granted the `roles/iam.serviceAccountTokenCreator` + // role + // on its next service account in the chain. The last service account in + // the + // chain must be granted the `roles/iam.serviceAccountTokenCreator` + // role + // on the service account that is specified in the `name` field of + // the + // request. + // + // The delegates must have the following + // format: + // `projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`. The `-` + // wildcard + // character is required; replacing it with a project ID is invalid. + Delegates []string `json:"delegates,omitempty"` + + // Payload: The JWT payload to sign: a JSON object that contains a JWT + // Claims Set. + Payload string `json:"payload,omitempty"` + + // ForceSendFields is a list of field names (e.g. "Delegates") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "Delegates") to include in + // API requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SignJwtRequest) MarshalJSON() ([]byte, error) { + type NoMethod SignJwtRequest + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +type SignJwtResponse struct { + // KeyId: The ID of the key used to sign the JWT. + KeyId string `json:"keyId,omitempty"` + + // SignedJwt: The signed JWT. + SignedJwt string `json:"signedJwt,omitempty"` + + // ServerResponse contains the HTTP response code and headers from the + // server. + googleapi.ServerResponse `json:"-"` + + // ForceSendFields is a list of field names (e.g. "KeyId") to + // unconditionally include in API requests. By default, fields with + // empty values are omitted from API requests. However, any non-pointer, + // non-interface field appearing in ForceSendFields will be sent to the + // server regardless of whether the field is empty or not. This may be + // used to include empty fields in Patch requests. + ForceSendFields []string `json:"-"` + + // NullFields is a list of field names (e.g. "KeyId") to include in API + // requests with the JSON null value. By default, fields with empty + // values are omitted from API requests. However, any field with an + // empty value appearing in NullFields will be sent to the server as + // null. It is an error if a field in this list has a non-empty value. + // This may be used to include null fields in Patch requests. + NullFields []string `json:"-"` +} + +func (s *SignJwtResponse) MarshalJSON() ([]byte, error) { + type NoMethod SignJwtResponse + raw := NoMethod(*s) + return gensupport.MarshalJSON(raw, s.ForceSendFields, s.NullFields) +} + +// method id "iamcredentials.projects.serviceAccounts.generateAccessToken": + +type ProjectsServiceAccountsGenerateAccessTokenCall struct { + s *Service + name string + generateaccesstokenrequest *GenerateAccessTokenRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// GenerateAccessToken: Generates an OAuth 2.0 access token for a +// service account. +func (r *ProjectsServiceAccountsService) GenerateAccessToken(name string, generateaccesstokenrequest *GenerateAccessTokenRequest) *ProjectsServiceAccountsGenerateAccessTokenCall { + c := &ProjectsServiceAccountsGenerateAccessTokenCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.generateaccesstokenrequest = generateaccesstokenrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsServiceAccountsGenerateAccessTokenCall) Fields(s ...googleapi.Field) *ProjectsServiceAccountsGenerateAccessTokenCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsServiceAccountsGenerateAccessTokenCall) Context(ctx context.Context) *ProjectsServiceAccountsGenerateAccessTokenCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsServiceAccountsGenerateAccessTokenCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsServiceAccountsGenerateAccessTokenCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + reqHeaders.Set("x-goog-api-client", "gl-go/1.11.0 gdcl/20190802") + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.generateaccesstokenrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:generateAccessToken") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "name": c.name, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "iamcredentials.projects.serviceAccounts.generateAccessToken" call. +// Exactly one of *GenerateAccessTokenResponse or error will be non-nil. +// Any non-2xx status code is an error. Response headers are in either +// *GenerateAccessTokenResponse.ServerResponse.Header or (if a response +// was returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *ProjectsServiceAccountsGenerateAccessTokenCall) Do(opts ...googleapi.CallOption) (*GenerateAccessTokenResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &GenerateAccessTokenResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Generates an OAuth 2.0 access token for a service account.", + // "flatPath": "v1/projects/{projectsId}/serviceAccounts/{serviceAccountsId}:generateAccessToken", + // "httpMethod": "POST", + // "id": "iamcredentials.projects.serviceAccounts.generateAccessToken", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The resource name of the service account for which the credentials\nare requested, in the following format:\n`projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`. The `-` wildcard\ncharacter is required; replacing it with a project ID is invalid.", + // "location": "path", + // "pattern": "^projects/[^/]+/serviceAccounts/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:generateAccessToken", + // "request": { + // "$ref": "GenerateAccessTokenRequest" + // }, + // "response": { + // "$ref": "GenerateAccessTokenResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "iamcredentials.projects.serviceAccounts.generateIdToken": + +type ProjectsServiceAccountsGenerateIdTokenCall struct { + s *Service + name string + generateidtokenrequest *GenerateIdTokenRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// GenerateIdToken: Generates an OpenID Connect ID token for a service +// account. +func (r *ProjectsServiceAccountsService) GenerateIdToken(name string, generateidtokenrequest *GenerateIdTokenRequest) *ProjectsServiceAccountsGenerateIdTokenCall { + c := &ProjectsServiceAccountsGenerateIdTokenCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.generateidtokenrequest = generateidtokenrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsServiceAccountsGenerateIdTokenCall) Fields(s ...googleapi.Field) *ProjectsServiceAccountsGenerateIdTokenCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsServiceAccountsGenerateIdTokenCall) Context(ctx context.Context) *ProjectsServiceAccountsGenerateIdTokenCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsServiceAccountsGenerateIdTokenCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsServiceAccountsGenerateIdTokenCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + reqHeaders.Set("x-goog-api-client", "gl-go/1.11.0 gdcl/20190802") + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.generateidtokenrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:generateIdToken") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "name": c.name, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "iamcredentials.projects.serviceAccounts.generateIdToken" call. +// Exactly one of *GenerateIdTokenResponse or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *GenerateIdTokenResponse.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *ProjectsServiceAccountsGenerateIdTokenCall) Do(opts ...googleapi.CallOption) (*GenerateIdTokenResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &GenerateIdTokenResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Generates an OpenID Connect ID token for a service account.", + // "flatPath": "v1/projects/{projectsId}/serviceAccounts/{serviceAccountsId}:generateIdToken", + // "httpMethod": "POST", + // "id": "iamcredentials.projects.serviceAccounts.generateIdToken", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The resource name of the service account for which the credentials\nare requested, in the following format:\n`projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`. The `-` wildcard\ncharacter is required; replacing it with a project ID is invalid.", + // "location": "path", + // "pattern": "^projects/[^/]+/serviceAccounts/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:generateIdToken", + // "request": { + // "$ref": "GenerateIdTokenRequest" + // }, + // "response": { + // "$ref": "GenerateIdTokenResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "iamcredentials.projects.serviceAccounts.signBlob": + +type ProjectsServiceAccountsSignBlobCall struct { + s *Service + name string + signblobrequest *SignBlobRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SignBlob: Signs a blob using a service account's system-managed +// private key. +func (r *ProjectsServiceAccountsService) SignBlob(name string, signblobrequest *SignBlobRequest) *ProjectsServiceAccountsSignBlobCall { + c := &ProjectsServiceAccountsSignBlobCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.signblobrequest = signblobrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsServiceAccountsSignBlobCall) Fields(s ...googleapi.Field) *ProjectsServiceAccountsSignBlobCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsServiceAccountsSignBlobCall) Context(ctx context.Context) *ProjectsServiceAccountsSignBlobCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsServiceAccountsSignBlobCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsServiceAccountsSignBlobCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + reqHeaders.Set("x-goog-api-client", "gl-go/1.11.0 gdcl/20190802") + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.signblobrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:signBlob") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "name": c.name, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "iamcredentials.projects.serviceAccounts.signBlob" call. +// Exactly one of *SignBlobResponse or error will be non-nil. Any +// non-2xx status code is an error. Response headers are in either +// *SignBlobResponse.ServerResponse.Header or (if a response was +// returned at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *ProjectsServiceAccountsSignBlobCall) Do(opts ...googleapi.CallOption) (*SignBlobResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &SignBlobResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Signs a blob using a service account's system-managed private key.", + // "flatPath": "v1/projects/{projectsId}/serviceAccounts/{serviceAccountsId}:signBlob", + // "httpMethod": "POST", + // "id": "iamcredentials.projects.serviceAccounts.signBlob", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The resource name of the service account for which the credentials\nare requested, in the following format:\n`projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`. The `-` wildcard\ncharacter is required; replacing it with a project ID is invalid.", + // "location": "path", + // "pattern": "^projects/[^/]+/serviceAccounts/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:signBlob", + // "request": { + // "$ref": "SignBlobRequest" + // }, + // "response": { + // "$ref": "SignBlobResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +} + +// method id "iamcredentials.projects.serviceAccounts.signJwt": + +type ProjectsServiceAccountsSignJwtCall struct { + s *Service + name string + signjwtrequest *SignJwtRequest + urlParams_ gensupport.URLParams + ctx_ context.Context + header_ http.Header +} + +// SignJwt: Signs a JWT using a service account's system-managed private +// key. +func (r *ProjectsServiceAccountsService) SignJwt(name string, signjwtrequest *SignJwtRequest) *ProjectsServiceAccountsSignJwtCall { + c := &ProjectsServiceAccountsSignJwtCall{s: r.s, urlParams_: make(gensupport.URLParams)} + c.name = name + c.signjwtrequest = signjwtrequest + return c +} + +// Fields allows partial responses to be retrieved. See +// https://developers.google.com/gdata/docs/2.0/basics#PartialResponse +// for more information. +func (c *ProjectsServiceAccountsSignJwtCall) Fields(s ...googleapi.Field) *ProjectsServiceAccountsSignJwtCall { + c.urlParams_.Set("fields", googleapi.CombineFields(s)) + return c +} + +// Context sets the context to be used in this call's Do method. Any +// pending HTTP request will be aborted if the provided context is +// canceled. +func (c *ProjectsServiceAccountsSignJwtCall) Context(ctx context.Context) *ProjectsServiceAccountsSignJwtCall { + c.ctx_ = ctx + return c +} + +// Header returns an http.Header that can be modified by the caller to +// add HTTP headers to the request. +func (c *ProjectsServiceAccountsSignJwtCall) Header() http.Header { + if c.header_ == nil { + c.header_ = make(http.Header) + } + return c.header_ +} + +func (c *ProjectsServiceAccountsSignJwtCall) doRequest(alt string) (*http.Response, error) { + reqHeaders := make(http.Header) + reqHeaders.Set("x-goog-api-client", "gl-go/1.11.0 gdcl/20190802") + for k, v := range c.header_ { + reqHeaders[k] = v + } + reqHeaders.Set("User-Agent", c.s.userAgent()) + var body io.Reader = nil + body, err := googleapi.WithoutDataWrapper.JSONReader(c.signjwtrequest) + if err != nil { + return nil, err + } + reqHeaders.Set("Content-Type", "application/json") + c.urlParams_.Set("alt", alt) + c.urlParams_.Set("prettyPrint", "false") + urls := googleapi.ResolveRelative(c.s.BasePath, "v1/{+name}:signJwt") + urls += "?" + c.urlParams_.Encode() + req, err := http.NewRequest("POST", urls, body) + if err != nil { + return nil, err + } + req.Header = reqHeaders + googleapi.Expand(req.URL, map[string]string{ + "name": c.name, + }) + return gensupport.SendRequest(c.ctx_, c.s.client, req) +} + +// Do executes the "iamcredentials.projects.serviceAccounts.signJwt" call. +// Exactly one of *SignJwtResponse or error will be non-nil. Any non-2xx +// status code is an error. Response headers are in either +// *SignJwtResponse.ServerResponse.Header or (if a response was returned +// at all) in error.(*googleapi.Error).Header. Use +// googleapi.IsNotModified to check whether the returned error was +// because http.StatusNotModified was returned. +func (c *ProjectsServiceAccountsSignJwtCall) Do(opts ...googleapi.CallOption) (*SignJwtResponse, error) { + gensupport.SetOptions(c.urlParams_, opts...) + res, err := c.doRequest("json") + if res != nil && res.StatusCode == http.StatusNotModified { + if res.Body != nil { + res.Body.Close() + } + return nil, &googleapi.Error{ + Code: res.StatusCode, + Header: res.Header, + } + } + if err != nil { + return nil, err + } + defer googleapi.CloseBody(res) + if err := googleapi.CheckResponse(res); err != nil { + return nil, err + } + ret := &SignJwtResponse{ + ServerResponse: googleapi.ServerResponse{ + Header: res.Header, + HTTPStatusCode: res.StatusCode, + }, + } + target := &ret + if err := gensupport.DecodeResponse(target, res); err != nil { + return nil, err + } + return ret, nil + // { + // "description": "Signs a JWT using a service account's system-managed private key.", + // "flatPath": "v1/projects/{projectsId}/serviceAccounts/{serviceAccountsId}:signJwt", + // "httpMethod": "POST", + // "id": "iamcredentials.projects.serviceAccounts.signJwt", + // "parameterOrder": [ + // "name" + // ], + // "parameters": { + // "name": { + // "description": "The resource name of the service account for which the credentials\nare requested, in the following format:\n`projects/-/serviceAccounts/{ACCOUNT_EMAIL_OR_UNIQUEID}`. The `-` wildcard\ncharacter is required; replacing it with a project ID is invalid.", + // "location": "path", + // "pattern": "^projects/[^/]+/serviceAccounts/[^/]+$", + // "required": true, + // "type": "string" + // } + // }, + // "path": "v1/{+name}:signJwt", + // "request": { + // "$ref": "SignJwtRequest" + // }, + // "response": { + // "$ref": "SignJwtResponse" + // }, + // "scopes": [ + // "https://www.googleapis.com/auth/cloud-platform" + // ] + // } + +}