Repository: dexidp/dex
Pull request #2651 (2022-09-07 04:05:53)

build(deps): bump github.com/lib/pq from 1.10.5 to 1.10.7
Bumps [github.com/lib/pq](https://github.com/lib/pq) from 1.10.5 to 1.10.7.
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/lib/pq/commit/d5affd5073b06f745459768de35356df2e5fd91d"><code>d5affd5</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/lib/pq/issues/1088">#1088</a> from kelvich/sni_support</li>
<li><a href="https://github.com/lib/pq/commit/d65e6ae4bdd1c86b16cd6d2bcff4fe970dc697b4"><code>d65e6ae</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/lib/pq/issues/1083">#1083</a> from nhooyr/fix-receiver-51e2</li>
<li><a href="https://github.com/lib/pq/commit/957fc0b40156534f8dd356bc81679d7e1365242b"><code>957fc0b</code></a> Set SNI for TSL connections</li>
<li><a href="https://github.com/lib/pq/commit/89fee896440712bc328c9087ea185c3990053f31"><code>89fee89</code></a> Use pointer receiver on pq.Error.Error()</li>
<li><a href="https://github.com/lib/pq/commit/8c6de565f76fb5cd40a5c1b8ce583fbc3ba1bd0e"><code>8c6de56</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/lib/pq/issues/1081">#1081</a> from catj-cockroach/add-kubernetes-secret-support</li>
<li><a href="https://github.com/lib/pq/commit/d8917faf2ecafe856e2cb2df95b51a96f58b3387"><code>d8917fa</code></a> adds support for kubernetes mounted private keys</li>
<li><a href="https://github.com/lib/pq/commit/54a3a4b3f393c97a92757204b31bfbb76473a1fb"><code>54a3a4b</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/lib/pq/issues/1082">#1082</a> from johanneswuerbach/connector-dialer</li>
<li><a href="https://github.com/lib/pq/commit/30d9faf71f714a01fc9d2a301915b97f226e0b52"><code>30d9faf</code></a> Merge pull request <a href="https://github-redirect.dependabot.com/lib/pq/issues/1080">#1080</a> from drakkan/sqlstate</li>
<li><a href="https://github.com/lib/pq/commit/cf6aeee4f29bfe6ca4eb95d3d577c98f271e40d7"><code>cf6aeee</code></a> feat: change the connector dialer</li>
<li><a href="https://github.com/lib/pq/commit/ef3111ea5aefd45f868ed58012b1d0d0dd162982"><code>ef3111e</code></a> error: add SQLState</li>
<li>Additional commits viewable in <a href="https://github.com/lib/pq/compare/v1.10.5...v1.10.7">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/lib/pq&package-manager=go_modules&previous-version=1.10.5&new-version=1.10.7)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
Dependabot will merge this PR once CI passes on it, as requested by @sagikazarmark.

[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Patch:
diff --git a/Dockerfile b/Dockerfile
index 1a2fda4c..3462ae52 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,6 +1,6 @@
 ARG BASE_IMAGE=alpine
 
-FROM golang:1.19.0-alpine3.15 AS builder
+FROM golang:1.19.1-alpine3.16 AS builder
 
 WORKDIR /usr/local/src/dex
 
diff --git a/api/v2/go.mod b/api/v2/go.mod
index d1eefc2e..dc78ec4d 100644
--- a/api/v2/go.mod
+++ b/api/v2/go.mod
@@ -4,7 +4,7 @@ go 1.17
 
 require (
 	google.golang.org/grpc v1.47.0
-	google.golang.org/protobuf v1.28.0
+	google.golang.org/protobuf v1.28.1
 )
 
 require (
diff --git a/api/v2/go.sum b/api/v2/go.sum
index a42fa0ce..59d53d2d 100644
--- a/api/v2/go.sum
+++ b/api/v2/go.sum
@@ -131,8 +131,9 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba
 google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
 google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
+google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
diff --git a/connector/google/google.go b/connector/google/google.go
index 1b515b8e..72cc6a18 100644
--- a/connector/google/google.go
+++ b/connector/google/google.go
@@ -71,7 +71,7 @@ func (c *Config) Open(id string, logger log.Logger) (conn connector.Connector, e
 		scopes = append(scopes, "profile", "email")
 	}
 
-	srv, err := createDirectoryService(c.ServiceAccountFilePath, c.AdminEmail)
+	srv, err := createDirectoryService(c.ServiceAccountFilePath, c.AdminEmail, logger)
 	if err != nil {
 		cancel()
 		return nil, fmt.Errorf("could not create directory service: %v", err)
@@ -279,37 +279,37 @@ func (c *googleConnector) getGroups(email string, fetchTransitiveGroupMembership
 	return uniqueGroups(userGroups), nil
 }
 
-// createDirectoryService loads a google service account credentials file,
-// sets up super user impersonation and creates an admin client for calling
-// the google admin api
-func createDirectoryService(serviceAccountFilePath string, email string) (*admin.Service, error) {
-	if serviceAccountFilePath == "" && email == "" {
-		return nil, nil
-	}
-	if serviceAccountFilePath == "" || email == "" {
-		return nil, fmt.Errorf("directory service requires both serviceAccountFilePath and adminEmail")
-	}
-	jsonCredentials, err := os.ReadFile(serviceAccountFilePath)
-	if err != nil {
-		return nil, fmt.Errorf("error reading credentials from file: %v", err)
+// createDirectoryService sets up super user impersonation and creates an admin client for calling
+// the google admin api. If no serviceAccountFilePath is defined, the application default credential
+// is used.
+func createDirectoryService(serviceAccountFilePath, email string, logger log.Logger) (*admin.Service, error) {
+	if email == "" {
+		return nil, fmt.Errorf("directory service requires adminEmail")
 	}
 
-	config, err := google.JWTConfigFromJSON(jsonCredentials, admin.AdminDirectoryGroupReadonlyScope)
-	if err != nil {
-		return nil, fmt.Errorf("unable to parse client secret file to config: %v", err)
-	}
-
-	// Impersonate an admin. This is mandatory for the admin APIs.
-	config.Subject = email
+	var jsonCredentials []byte
+	var err error
 
 	ctx := context.Background()
-	client := config.Client(ctx)
-
-	srv, err := admin.NewService(ctx, option.WithHTTPClient(client))
+	if serviceAccountFilePath == "" {
+		logger.Warn("the application default credential is used since the service account file path is not used")
+		credential, err := google.FindDefaultCredentials(ctx)
+		if err != nil {
+			return nil, fmt.Errorf("failed to fetch application default credentials: %w", err)
+		}
+		jsonCredentials = credential.JSON
+	} else {
+		jsonCredentials, err = os.ReadFile(serviceAccountFilePath)
+		if err != nil {
+			return nil, fmt.Errorf("error reading credentials from file: %v", err)
+		}
+	}
+	config, err := google.JWTConfigFromJSON(jsonCredentials, admin.AdminDirectoryGroupReadonlyScope)
 	if err != nil {
-		return nil, fmt.Errorf("unable to create directory service %v", err)
+		return nil, fmt.Errorf("unable to parse credentials to config: %v", err)
 	}
-	return srv, nil
+	config.Subject = email
+	return admin.NewService(ctx, option.WithHTTPClient(config.Client(ctx)))
 }
 
 // uniqueGroups returns the unique groups of a slice
diff --git a/flake.lock b/flake.lock
index f1a44670..b67b61d9 100644
--- a/flake.lock
+++ b/flake.lock
@@ -2,11 +2,11 @@
   "nodes": {
     "flake-utils": {
       "locked": {
-        "lastModified": 1648297722,
-        "narHash": "sha256-W+qlPsiZd8F3XkzXOzAoR+mpFqzm3ekQkJNa+PIh1BQ=",
+        "lastModified": 1659877975,
+        "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
         "owner": "numtide",
         "repo": "flake-utils",
-        "rev": "0f8662f1319ad6abf89b3380dd2722369fc51ade",
+        "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
         "type": "github"
       },
       "original": {
@@ -17,11 +17,11 @@
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1649225869,
-        "narHash": "sha256-u1zLtPmQzhT9mNXyM8Ey9pk7orDrIKdwooeGDEXm5xM=",
+        "lastModified": 1662019588,
+        "narHash": "sha256-oPEjHKGGVbBXqwwL+UjsveJzghWiWV0n9ogo1X6l4cw=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "b6966d911da89e5a7301aaef8b4f0a44c77e103c",
+        "rev": "2da64a81275b68fdad38af669afeda43d401e94b",
         "type": "github"
       },
       "original": {
diff --git a/flake.nix b/flake.nix
index 57aa2b05..155ebf99 100644
--- a/flake.nix
+++ b/flake.nix
@@ -7,19 +7,21 @@
   };
 
   outputs = { self, nixpkgs, flake-utils, ... }:
-    flake-utils.lib.eachDefaultSystem (system:
-      let
-        pkgs = nixpkgs.legacyPackages.${system};
-        buildDeps = with pkgs; [ git go_1_18 gnumake ];
-        devDeps = with pkgs;
-          buildDeps ++ [
-            golangci-lint
-            gotestsum
-            protobuf
-            protoc-gen-go
-            protoc-gen-go-grpc
-            kind
-          ];
-      in
-      { devShell = pkgs.mkShell { buildInputs = devDeps; }; });
+    flake-utils.lib.eachDefaultSystem (
+      system:
+        let
+          pkgs = nixpkgs.legacyPackages.${system};
+          buildDeps = with pkgs; [ git go_1_19 gnumake ];
+          devDeps = with pkgs;
+            buildDeps ++ [
+              golangci-lint
+              gotestsum
+              protobuf
+              protoc-gen-go
+              protoc-gen-go-grpc
+              kind
+            ];
+        in
+          { devShell = pkgs.mkShell { buildInputs = devDeps; }; }
+    );
 }
diff --git a/go.mod b/go.mod
index b5866377..95e65d4f 100644
--- a/go.mod
+++ b/go.mod
@@ -18,7 +18,7 @@ require (
 	github.com/gorilla/mux v1.8.0
 	github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
 	github.com/kylelemons/godebug v1.1.0
-	github.com/lib/pq v1.10.5
+	github.com/lib/pq v1.10.7
 	github.com/mattermost/xml-roundtrip-validator v0.1.0
 	github.com/mattn/go-sqlite3 v1.14.15
 	github.com/oklog/run v1.1.0
@@ -34,7 +34,7 @@ require (
 	golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b
 	golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094
 	google.golang.org/api v0.94.0
-	google.golang.org/grpc v1.47.0
+	google.golang.org/grpc v1.49.0
 	google.golang.org/protobuf v1.28.1
 	gopkg.in/square/go-jose.v2 v2.6.0
 )
diff --git a/go.sum b/go.sum
index 4a53013b..e4479e7c 100644
--- a/go.sum
+++ b/go.sum
@@ -300,8 +300,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
 github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
 github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
-github.com/lib/pq v1.10.5 h1:J+gdV2cUmX7ZqL2B0lFcW0m+egaHC2V3lpO8nWxyYiQ=
-github.com/lib/pq v1.10.5/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
+github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
+github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 github.com/mattermost/xml-roundtrip-validator v0.1.0 h1:RXbVD2UAl7A7nOTR4u7E3ILa4IbtvKBHw64LDsmu9hU=
 github.com/mattermost/xml-roundtrip-validator v0.1.0/go.mod h1:qccnGMcpgwcNaBnxqpJpWWUiPNr5H3O8eDgGV9gT5To=
 github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
@@ -868,8 +868,9 @@ google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ5
 google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
 google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
 google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
-google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8=
 google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
+google.golang.org/grpc v1.49.0 h1:WTLtQzmQori5FUH25Pq4WT22oCsv8USpQ+F6rqtsmxw=
+google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI=
 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
 google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
 google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=


Test patch:
diff --git a/connector/google/google_test.go b/connector/google/google_test.go
new file mode 100644
index 00000000..5cecbec9
--- /dev/null
+++ b/connector/google/google_test.go
@@ -0,0 +1,145 @@
+package google
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"net/http/httptest"
+	"os"
+	"testing"
+
+	"github.com/sirupsen/logrus"
+	"github.com/stretchr/testify/assert"
+)
+
+func testSetup(t *testing.T) *httptest.Server {
+	mux := http.NewServeMux()
+	// TODO: mock calls
+	// mux.HandleFunc("/admin/directory/v1/groups", func(w http.ResponseWriter, r *http.Request) {
+	// 	w.Header().Add("Content-Type", "application/json")
+	// 	json.NewEncoder(w).Encode(&admin.Groups{
+	// 		Groups: []*admin.Group{},
+	// 	})
+	// })
+	return httptest.NewServer(mux)
+}
+
+func newConnector(config *Config, serverURL string) (*googleConnector, error) {
+	log := logrus.New()
+	conn, err := config.Open("id", log)
+	if err != nil {
+		return nil, err
+	}
+
+	googleConn, ok := conn.(*googleConnector)
+	if !ok {
+		return nil, fmt.Errorf("failed to convert to googleConnector")
+	}
+	return googleConn, nil
+}
+
+func tempServiceAccountKey() (string, error) {
+	fd, err := os.CreateTemp("", "google_service_account_key")
+	if err != nil {
+		return "", err
+	}
+	defer fd.Close()
+	err = json.NewEncoder(fd).Encode(map[string]string{
+		"type":                 "service_account",
+		"project_id":           "sample-project",
+		"private_key_id":       "sample-key-id",
+		"private_key":          "-----BEGIN PRIVATE KEY-----\nsample-key\n-----END PRIVATE KEY-----\n",
+		"client_id":            "sample-client-id",
+		"client_x509_cert_url": "localhost",
+	})
+	return fd.Name(), err
+}
+
+func TestOpen(t *testing.T) {
+	ts := testSetup(t)
+	defer ts.Close()
+
+	type testCase struct {
+		config      *Config
+		expectedErr string
+
+		// string to set in GOOGLE_APPLICATION_CREDENTIALS. As local development environments can
+		// already contain ADC, test cases will be built uppon this setting this env variable
+		adc string
+	}
+
+	serviceAccountFilePath, err := tempServiceAccountKey()
+	assert.Nil(t, err)
+
+	for name, reference := range map[string]testCase{
+		"missing_admin_email": {
+			config: &Config{
+				ClientID:     "testClient",
+				ClientSecret: "testSecret",
+				RedirectURI:  ts.URL + "/callback",
+				Scopes:       []string{"openid", "groups"},
+			},
+			expectedErr: "requires adminEmail",
+		},
+		"service_account_key_not_found": {
+			config: &Config{
+				ClientID:               "testClient",
+				ClientSecret:           "testSecret",
+				RedirectURI:            ts.URL + "/callback",
+				Scopes:                 []string{"openid", "groups"},
+				AdminEmail:             "foo@bar.com",
+				ServiceAccountFilePath: "not_found.json",
+			},
+			expectedErr: "error reading credentials",
+		},
+		"service_account_key_valid": {
+			config: &Config{
+				ClientID:               "testClient",
+				ClientSecret:           "testSecret",
+				RedirectURI:            ts.URL + "/callback",
+				Scopes:                 []string{"openid", "groups"},
+				AdminEmail:             "foo@bar.com",
+				ServiceAccountFilePath: serviceAccountFilePath,
+			},
+			expectedErr: "",
+		},
+		"adc": {
+			config: &Config{
+				ClientID:     "testClient",
+				ClientSecret: "testSecret",
+				RedirectURI:  ts.URL + "/callback",
+				Scopes:       []string{"openid", "groups"},
+				AdminEmail:   "foo@bar.com",
+			},
+			adc:         serviceAccountFilePath,
+			expectedErr: "",
+		},
+		"adc_priority": {
+			config: &Config{
+				ClientID:               "testClient",
+				ClientSecret:           "testSecret",
+				RedirectURI:            ts.URL + "/callback",
+				Scopes:                 []string{"openid", "groups"},
+				AdminEmail:             "foo@bar.com",
+				ServiceAccountFilePath: serviceAccountFilePath,
+			},
+			adc:         "/dev/null",
+			expectedErr: "",
+		},
+	} {
+		reference := reference
+		t.Run(name, func(t *testing.T) {
+			assert := assert.New(t)
+
+			os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", reference.adc)
+			conn, err := newConnector(reference.config, ts.URL)
+
+			if reference.expectedErr == "" {
+				assert.Nil(err)
+				assert.NotNil(conn)
+			} else {
+				assert.ErrorContains(err, reference.expectedErr)
+			}
+		})
+	}
+}