This repository has been archived by the owner on Jun 27, 2021. It is now read-only.
/
config.go
124 lines (102 loc) · 3.58 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package gsuite
import (
"context"
"encoding/json"
"fmt"
"log"
"net/http"
"runtime"
"strings"
"github.com/hashicorp/terraform/helper/logging"
"github.com/hashicorp/terraform/helper/pathorcontents"
"github.com/hashicorp/terraform/terraform"
"github.com/pkg/errors"
"golang.org/x/oauth2/google"
"golang.org/x/oauth2/jwt"
directory "google.golang.org/api/admin/directory/v1"
)
var defaultOauthScopes = []string{
directory.AdminDirectoryGroupScope,
directory.AdminDirectoryUserScope,
directory.AdminDirectoryUserschemaScope,
}
// Config is the structure used to instantiate the GSuite provider.
type Config struct {
Credentials string
// Only users with access to the Admin APIs can access the Admin SDK Directory API,
// therefore the service account needs to impersonate one of those users to access the Admin SDK Directory API.
// See https://developers.google.com/admin-sdk/directory/v1/guides/delegation
ImpersonatedUserEmail string
CustomerId string
OauthScopes []string
directory *directory.Service
}
// loadAndValidate loads the application default credentials from the
// environment and creates a client for communicating with Google APIs.
func (c *Config) loadAndValidate() error {
log.Println("[INFO] Building gsuite client config structure")
var account accountFile
oauthScopes := c.OauthScopes
var client *http.Client
if c.Credentials != "" {
if c.ImpersonatedUserEmail == "" {
return fmt.Errorf("required field missing: impersonated_user_email")
}
contents, _, err := pathorcontents.Read(c.Credentials)
if err != nil {
return fmt.Errorf("Error loading credentials: %s", err)
}
// Assume account_file is a JSON string
if err := parseJSON(&account, contents); err != nil {
return fmt.Errorf("Error parsing credentials '%s': %s", contents, err)
}
// Get the token for use in our requests
log.Printf("[INFO] Requesting Google token...")
log.Printf("[INFO] -- Email: %s", account.ClientEmail)
log.Printf("[INFO] -- Scopes: %s", oauthScopes)
log.Printf("[INFO] -- Private Key Length: %d", len(account.PrivateKey))
conf := jwt.Config{
Email: account.ClientEmail,
PrivateKey: []byte(account.PrivateKey),
Scopes: oauthScopes,
TokenURL: "https://accounts.google.com/o/oauth2/token",
}
conf.Subject = c.ImpersonatedUserEmail
// Initiate an http.Client. The following GET request will be
// authorized and authenticated on the behalf of
// your service account.
client = conf.Client(context.Background())
} else {
log.Printf("[INFO] Authenticating using DefaultClient")
err := error(nil)
client, err = google.DefaultClient(context.Background(), oauthScopes...)
if err != nil {
return errors.Wrap(err, "failed to create client")
}
}
// Use a custom user-agent string. This helps google with analytics and it's
// just a nice thing to do.
client.Transport = logging.NewTransport("Google", client.Transport)
userAgent := fmt.Sprintf("(%s %s) Terraform/%s",
runtime.GOOS, runtime.GOARCH, terraform.VersionString())
// Create the directory service.
directorySvc, err := directory.New(client)
if err != nil {
return nil
}
directorySvc.UserAgent = userAgent
c.directory = directorySvc
return nil
}
// accountFile represents the structure of the account file JSON file.
type accountFile struct {
PrivateKeyId string `json:"private_key_id"`
PrivateKey string `json:"private_key"`
ClientEmail string `json:"client_email"`
ClientId string `json:"client_id"`
}
func parseJSON(result interface{}, contents string) error {
r := strings.NewReader(contents)
dec := json.NewDecoder(r)
return dec.Decode(result)
}