1// Copyright 2018 The Go Cloud Development Kit Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// Package gcp provides fundamental Wire providers and types for Google Cloud Platform (GCP).
16package gcp // import "gocloud.dev/gcp"
17
18import (
19	"context"
20	"errors"
21	"net/http"
22
23	"github.com/google/wire"
24	"golang.org/x/oauth2"
25	"golang.org/x/oauth2/google"
26)
27
28// DefaultIdentity is a Wire provider set that provides the project ID
29// and token source from Application Default Credentials (ADC).
30var DefaultIdentity = wire.NewSet(
31	CredentialsTokenSource,
32	DefaultCredentials,
33	DefaultProjectID)
34
35// ProjectID is a GCP Project ID.
36type ProjectID string
37
38// TokenSource wraps a GCP token source that provides Cloud-Platform-
39// scoped tokens.
40type TokenSource oauth2.TokenSource
41
42// HTTPClient is an HTTP client that makes requests authenticated with Cloud-
43// Platform-scoped authentication tokens.
44type HTTPClient struct {
45	http.Client
46}
47
48// NewAnonymousHTTPClient creates a new anonymous HTTP client.
49func NewAnonymousHTTPClient(transport http.RoundTripper) *HTTPClient {
50	return &HTTPClient{
51		Client: http.Client{
52			Transport: transport,
53		},
54	}
55}
56
57// NewHTTPClient creates a new authenticated HTTP client.
58func NewHTTPClient(transport http.RoundTripper, ts TokenSource) (*HTTPClient, error) {
59	if ts == nil {
60		return nil, errors.New("gcp: no credentials available")
61	}
62	return &HTTPClient{
63		Client: http.Client{
64			Transport: &oauth2.Transport{
65				Base:   transport,
66				Source: ts,
67			},
68		},
69	}, nil
70}
71
72// DefaultTransport returns http.DefaultTransport.
73func DefaultTransport() http.RoundTripper {
74	return http.DefaultTransport
75}
76
77// DefaultCredentials obtains the default GCP credentials with Cloud Platform
78// scope.
79func DefaultCredentials(ctx context.Context) (*google.Credentials, error) {
80	adc, err := google.FindDefaultCredentials(ctx, "https://www.googleapis.com/auth/cloud-platform")
81	if err != nil {
82		return nil, err
83	}
84	return adc, nil
85}
86
87// CredentialsTokenSource extracts the token source from GCP credentials.
88func CredentialsTokenSource(creds *google.Credentials) TokenSource {
89	if creds == nil {
90		return nil
91	}
92	return TokenSource(creds.TokenSource)
93}
94
95// DefaultProjectID obtains the project ID from the default GCP credentials.
96func DefaultProjectID(creds *google.Credentials) (ProjectID, error) {
97	if creds == nil {
98		return "", errors.New("gcp: no project found in credentials")
99	}
100	return ProjectID(creds.ProjectID), nil
101}
102