Skip to content

Commit f11f9e0

Browse files
committed
Support Impersonate Service Account
Added support for Impersonate Service Account as a way to send a Request to IAP without creating a Service Account Key. https://cloud.google.com/iam/docs/impersonating-service-accounts
1 parent 5e7169f commit f11f9e0

File tree

6 files changed

+536
-169
lines changed

6 files changed

+536
-169
lines changed

README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,22 @@ iap_curl
55

66
## Usage
77

8+
### Option1: Use Application Default Credential
9+
810
```console
911
$ export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"
1012
$ export IAP_CLIENT_ID="342624545358-asdfd8fas9df8sd7ga0sdguadfpvqp69.apps.googleusercontent.com"
1113
$ iap_curl http://iap-protected.webapp.com
1214
```
1315

16+
### Option2: Use [Impersonate Service Account](https://cloud.google.com/iam/docs/impersonating-service-accounts)
17+
18+
```console
19+
$ export CLOUDSDK_AUTH_IMPERSONATE_SERVICE_ACCOUNT="[email protected]"
20+
$ export IAP_CLIENT_ID="342624545358-asdfd8fas9df8sd7ga0sdguadfpvqp69.apps.googleusercontent.com"
21+
$ iap_curl http://iap-protected.webapp.com
22+
```
23+
1424
The options of `iap_curl` are fully compatible with `curl` command.
1525

1626
If you want to use [httpstat](https://github.com/b4b4r07/httpstat) instead of `curl`, please specify `IAP_CURL_BIN` environment variable:
@@ -50,6 +60,8 @@ Body discarded
5060

5161
You can save the URL of frequently used service together with its Env (`IAP_CLIENT_ID` ...) in a JSON file (see also [#1](https://github.com/b4b4r07/iap_curl/issues/1)). This file is located in `~/.config/iap_curl/config.json`.
5262

63+
### Option1: Use Application Default Credential
64+
5365
```json
5466
{
5567
"services": [
@@ -65,6 +77,23 @@ You can save the URL of frequently used service together with its Env (`IAP_CLIE
6577
}
6678
```
6779

80+
### Option2: Use [Impersonate Service Account](https://cloud.google.com/iam/docs/impersonating-service-accounts)
81+
82+
```json
83+
{
84+
"services": [
85+
{
86+
"url": "https://my.service.com/health",
87+
"env": {
88+
"CLOUDSDK_AUTH_IMPERSONATE_SERVICE_ACCOUNT": "[email protected]",
89+
"IAP_CLIENT_ID": "839558305167-s3akt4doo38lckhaac1ucfdp0e4921tc.apps.googleusercontent.com",
90+
"IAP_CURL_BIN": "curl"
91+
}
92+
}
93+
]
94+
}
95+
```
96+
6897
Thanks to that, you can access more easier like curl.
6998

7099
```console

config.go

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ import (
1616
)
1717

1818
const (
19-
envCredentials = "GOOGLE_APPLICATION_CREDENTIALS"
20-
envClientID = "IAP_CLIENT_ID"
21-
envCurlCommand = "IAP_CURL_BIN"
19+
envCredentials = "GOOGLE_APPLICATION_CREDENTIALS"
20+
envImpersonateServiceAccount = "CLOUDSDK_AUTH_IMPERSONATE_SERVICE_ACCOUNT"
21+
envClientID = "IAP_CLIENT_ID"
22+
envCurlCommand = "IAP_CURL_BIN"
2223
)
2324

2425
// Config represents
@@ -37,9 +38,10 @@ type Service struct {
3738

3839
// Env represents the environment variables needed to request to IAP-protected app
3940
type Env struct {
40-
Credentials string `json:"GOOGLE_APPLICATION_CREDENTIALS"`
41-
ClientID string `json:"IAP_CLIENT_ID"`
42-
Binary string `json:"IAP_CURL_BIN"`
41+
Credentials string `json:"GOOGLE_APPLICATION_CREDENTIALS"`
42+
ImpersonateServiceAccount string `json:"CLOUDSDK_AUTH_IMPERSONATE_SERVICE_ACCOUNT"`
43+
ClientID string `json:"IAP_CLIENT_ID"`
44+
Binary string `json:"IAP_CURL_BIN"`
4345
}
4446

4547
func configDir() (string, error) {
@@ -125,19 +127,23 @@ func (cfg *Config) getEnvFromFile(url string) (env Env, err error) {
125127
func (cfg *Config) GetEnv(url string) (env Env, err error) {
126128
env, _ = cfg.getEnvFromFile(url)
127129
credentials := os.Getenv(envCredentials)
130+
impersonateServiceAccount := os.Getenv(envImpersonateServiceAccount)
128131
clientID := os.Getenv(envClientID)
129132
binary := os.Getenv(envCurlCommand)
130133
if credentials == "" {
131134
credentials, _ = homedir.Expand(env.Credentials)
132135
}
136+
if impersonateServiceAccount == "" {
137+
impersonateServiceAccount, _ = homedir.Expand(env.ImpersonateServiceAccount)
138+
}
133139
if clientID == "" {
134140
clientID = env.ClientID
135141
}
136142
if binary == "" {
137143
binary = env.Binary
138144
}
139-
if credentials == "" {
140-
return env, fmt.Errorf("%s is missing", envCredentials)
145+
if credentials == "" && impersonateServiceAccount == "" {
146+
return env, fmt.Errorf("%s and %s is missing. Either is required", envCredentials, envImpersonateServiceAccount)
141147
}
142148
if clientID == "" {
143149
return env, fmt.Errorf("%s is missing", envClientID)
@@ -146,9 +152,10 @@ func (cfg *Config) GetEnv(url string) (env Env, err error) {
146152
binary = "curl"
147153
}
148154
return Env{
149-
Credentials: credentials,
150-
ClientID: clientID,
151-
Binary: binary,
155+
Credentials: credentials,
156+
ImpersonateServiceAccount: impersonateServiceAccount,
157+
ClientID: clientID,
158+
Binary: binary,
152159
}, nil
153160
}
154161

go.mod

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,9 @@ module github.com/b4b4r07/iap_curl
33
go 1.12
44

55
require (
6-
cloud.google.com/go v0.16.0 // indirect
76
github.com/alessio/shellescape v0.0.0-20190409004728-b115ca0f9053 // indirect
8-
github.com/golang/protobuf v0.0.0-20171113180720-1e59b77b52bf // indirect
7+
github.com/apstndb/tokensource v0.0.0-20210528072307-642759746b05
98
github.com/hashicorp/logutils v1.0.0
109
github.com/mitchellh/go-homedir v0.0.0-20161203194507-b8bc1bf76747
11-
golang.org/x/net v0.0.0-20171123081856-c7086645de24 // indirect
12-
golang.org/x/oauth2 v0.0.0-20171117235251-f95fa95eaa93
13-
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect
14-
google.golang.org/appengine v1.0.0 // indirect
1510
gopkg.in/alessio/shellescape.v1 v1.0.0-20170105083845-52074bc9df61
1611
)

0 commit comments

Comments
 (0)