From 0689666873bc3b1a267ba98873c5f85355345fcc Mon Sep 17 00:00:00 2001 From: stevenGravy Date: Fri, 12 Feb 2021 16:37:23 -0500 Subject: [PATCH 01/22] Add google_service_account field to OIDC for specifying google service account json --- api/types/oidc.go | 30 +++++++++++++++++++++- lib/auth/oidc.go | 50 ++++++++++++++++++++++++------------- lib/services/local/users.go | 6 +++++ lib/services/oidc.go | 13 ++++++++++ 4 files changed, 80 insertions(+), 19 deletions(-) diff --git a/api/types/oidc.go b/api/types/oidc.go index 23c8439ebf773..ca70878f876a0 100644 --- a/api/types/oidc.go +++ b/api/types/oidc.go @@ -88,6 +88,10 @@ type OIDCConnector interface { // GetGoogleAdminEmail returns a google admin user email // https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority // "Note: Although you can use service accounts in applications that run from a G Suite domain, service accounts are not members of your G Suite account and aren’t subject to domain policies set by G Suite administrators. For example, a policy set in the G Suite admin console to restrict the ability of G Suite end users to share documents outside of the domain would not apply to service accounts." + GetGoogleServiceAccount() string + // GetGoogleServiceAccount retrieves service account json for Google + SetGoogleServiceAccount(string) + // sets the service account json for Google GetGoogleAdminEmail() string } @@ -139,6 +143,16 @@ func (o *OIDCConnectorV2) GetGoogleServiceAccountURI() string { return o.Spec.GoogleServiceAccountURI } +// GetGoogleServiceAccountURI returns an optional path to google service account file +func (o *OIDCConnectorV2) GetGoogleServiceAccount() string { + return o.Spec.GoogleServiceAccount +} + +// SetResourceID sets resource ID +func (o *OIDCConnectorV2) SetGoogleServiceAccount(s string) { + o.Spec.GoogleServiceAccount = s +} + // GetGoogleAdminEmail returns a google admin user email func (o *OIDCConnectorV2) GetGoogleAdminEmail() string { return o.Spec.GoogleAdminEmail @@ -176,11 +190,22 @@ func (o *OIDCConnectorV2) SetResourceID(id int64) { // WithoutSecrets returns an instance of resource without secrets. func (o *OIDCConnectorV2) WithoutSecrets() Resource { - if o.GetClientSecret() == "" { + if (o.GetClientSecret() == "" && o.GetGoogleServiceAccount() == "" ) { return o } o2 := *o + + if (o.GetClientSecret() != "") { o2.SetClientSecret("") +} + + if (o.GetGoogleServiceAccount() != "" ) { + // emptyGoogleserviceaccount := "" + + o2.SetGoogleServiceAccount("") + + } + return &o2 } @@ -410,6 +435,9 @@ type OIDCConnectorSpecV2 struct { ClaimsToRoles []ClaimMapping `json:"claims_to_roles,omitempty"` // GoogleServiceAccountURI is a path to google service account uri GoogleServiceAccountURI string `json:"google_service_account_uri,omitempty"` + // GoogleServiceAccount is the contents of the google service account credentials + GoogleServiceAccount string `json:"google_service_account,omitempty"` + // GoogleAdminEmail is email of google admin to impersonate GoogleAdminEmail string `json:"google_admin_email,omitempty"` } diff --git a/lib/auth/oidc.go b/lib/auth/oidc.go index 2adf73214a873..eb79323e3df32 100644 --- a/lib/auth/oidc.go +++ b/lib/auth/oidc.go @@ -668,7 +668,7 @@ collect: for { if count > MaxPages { warningMessage := "Truncating list of teams used to populate claims: " + - "hit maximum number pages that can be fetched from GSuite." + "hit maximum number pages that can be fetched from Google Workspace." // Print warning to Teleport logs as well as the Audit Log. log.Warnf(warningMessage) @@ -714,7 +714,7 @@ func (g *gsuiteClient) fetchGroupsPage(pageToken string) (*gsuiteGroups, error) u.RawQuery = q.Encode() endpoint := u.String() - log.Debugf("Fetching OIDC claims from GSuite groups endpoint: %q.", endpoint) + log.Debugf("Fetching OIDC claims from Google Workspace groups endpoint: %q.", endpoint) req, err := http.NewRequest("GET", endpoint, nil) if err != nil { @@ -835,32 +835,46 @@ func (a *Server) getClaims(oidcClient *oidc.Client, connector services.OIDCConne return nil, trace.Wrap(err) } + var config *jwt.Config + var jsonCredentials []byte + + //load the google service account uri from + if(connector.GetGoogleServiceAccountURI()!="") { + serviceAccountURI := connector.GetGoogleServiceAccountURI() if serviceAccountURI == "" { return nil, trace.NotFound( - "the gsuite connector requires google_service_account_uri parameter to be specified and pointing to a valid google service account file with credentials, read this article for more details https://developers.google.com/admin-sdk/directory/v1/guides/delegation") + "the google workspace connector requires google_service_account_uri parameter to be specified and pointing to a valid google service account file with credentials, read this article for more details https://developers.google.com/admin-sdk/directory/v1/guides/delegation") } uri, err := utils.ParseSessionsURI(serviceAccountURI) if err != nil { return nil, trace.BadParameter("failed to parse google_service_account_uri: %v", err) } - - impersonateAdmin := connector.GetGoogleAdminEmail() - if impersonateAdmin == "" { - return nil, trace.NotFound( - "the gsuite connector requires google_admin_email user to impersonate, as service accounts can not be used directly https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority") - } - - jsonCredentials, err := ioutil.ReadFile(uri.Path) + jsonCredentials, err = ioutil.ReadFile(uri.Path) if err != nil { return nil, trace.Wrap(err) } - config, err := google.JWTConfigFromJSON(jsonCredentials, teleport.GSuiteGroupsScope) - if err != nil { - return nil, trace.BadParameter("unable to parse client secret file to config: %v", err) - } + } else if(connector.GetGoogleServiceAccount()!="") { + + jsonCredentials = []byte(connector.GetGoogleServiceAccount()) + } + + config, err = google.JWTConfigFromJSON(jsonCredentials, teleport.GSuiteGroupsScope) + if err != nil { + return nil, trace.BadParameter("unable to parse client secret file to config: %v", err) + } + + + impersonateAdmin := connector.GetGoogleAdminEmail() + if impersonateAdmin == "" { + return nil, trace.NotFound( + "the google workspace connector requires google_admin_email user to impersonate, as service accounts can not be used directly https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority") + } + + + // User should impersonate admin user, otherwise it won't work: // // https://developers.google.com/admin-sdk/directory/v1/guides/delegation @@ -869,7 +883,7 @@ func (a *Server) getClaims(oidcClient *oidc.Client, connector services.OIDCConne // domain, exists, err := userInfoClaims.StringClaim(teleport.GSuiteDomainClaim) if err != nil || !exists { - return nil, trace.BadParameter("hd is the required claim for GSuite") + return nil, trace.BadParameter("hd is the required claim for Google Workspace") } config.Subject = impersonateAdmin @@ -878,10 +892,10 @@ func (a *Server) getClaims(oidcClient *oidc.Client, connector services.OIDCConne if !trace.IsNotFound(err) { return nil, trace.Wrap(err) } - log.Debugf("Found no GSuite claims.") + log.Debugf("Found no Google Workspace claims.") } else { if gsuiteClaims != nil { - log.Debugf("Got GSuiteclaims: %v.", gsuiteClaims) + log.Debugf("Got GoogleWorkspace claims: %v.", gsuiteClaims) } claims, err = mergeClaims(claims, gsuiteClaims) if err != nil { diff --git a/lib/services/local/users.go b/lib/services/local/users.go index 9140f6881b088..38e151cd46df4 100644 --- a/lib/services/local/users.go +++ b/lib/services/local/users.go @@ -705,6 +705,9 @@ func (s *IdentityService) GetOIDCConnector(name string, withSecrets bool) (servi } if !withSecrets { conn.SetClientSecret("") + if(conn.GetGoogleServiceAccount() != "") { + conn.SetGoogleServiceAccount("") + } } return conn, nil } @@ -725,6 +728,9 @@ func (s *IdentityService) GetOIDCConnectors(withSecrets bool) ([]services.OIDCCo } if !withSecrets { conn.SetClientSecret("") + if(conn.GetGoogleServiceAccount() != "") { + conn.SetGoogleServiceAccount("") + } } connectors[i] = conn } diff --git a/lib/services/oidc.go b/lib/services/oidc.go index ea1dd5de058c8..6c2e5e94a31d4 100644 --- a/lib/services/oidc.go +++ b/lib/services/oidc.go @@ -38,6 +38,13 @@ func ValidateOIDCConnector(oc types.OIDCConnector) error { if _, err := url.Parse(oc.GetRedirectURL()); err != nil { return trace.BadParameter("RedirectURL: bad url: '%v'", oc.GetRedirectURL()) } + + + + if ( (oc.GetGoogleServiceAccountURI() != "") && (oc.GetGoogleServiceAccount() != "") ) { + return trace.BadParameter("google_service_account_uri or google_service_account is supported, not both") + } + if oc.GetGoogleServiceAccountURI() != "" { uri, err := utils.ParseSessionsURI(oc.GetGoogleServiceAccountURI()) if err != nil { @@ -50,6 +57,11 @@ func ValidateOIDCConnector(oc types.OIDCConnector) error { return trace.BadParameter("whenever google_service_account_uri is specified, google_admin_email should be set as well, read https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority for more details") } } + if oc.GetGoogleServiceAccount() != "" { + if oc.GetGoogleAdminEmail() == "" { + return trace.BadParameter("whenever google_service_account is specified, google_admin_email should be set as well, read https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority for more details") + } + } return nil } @@ -95,6 +107,7 @@ var OIDCConnectorSpecV2Schema = fmt.Sprintf(`{ "display": {"type": "string"}, "prompt": {"type": "string"}, "google_service_account_uri": {"type": "string"}, + "google_service_account": {"type": "string"}, "google_admin_email": {"type": "string"}, "scope": { "type": "array", From 6b24cf15f615f4d53a5c9e93bc76ea0ab55451f2 Mon Sep 17 00:00:00 2001 From: stevenGravy Date: Fri, 12 Feb 2021 17:11:43 -0500 Subject: [PATCH 02/22] corrected lint issues --- api/types/oidc.go | 17 +++++------ lib/auth/oidc.go | 58 +++++++++++++++++-------------------- lib/services/local/users.go | 12 ++++---- lib/services/oidc.go | 8 ++--- 4 files changed, 43 insertions(+), 52 deletions(-) diff --git a/api/types/oidc.go b/api/types/oidc.go index ca70878f876a0..44c13c85f7633 100644 --- a/api/types/oidc.go +++ b/api/types/oidc.go @@ -190,21 +190,18 @@ func (o *OIDCConnectorV2) SetResourceID(id int64) { // WithoutSecrets returns an instance of resource without secrets. func (o *OIDCConnectorV2) WithoutSecrets() Resource { - if (o.GetClientSecret() == "" && o.GetGoogleServiceAccount() == "" ) { + if o.GetClientSecret() == "" && o.GetGoogleServiceAccount() == "" { return o } o2 := *o - if (o.GetClientSecret() != "") { - o2.SetClientSecret("") -} - - if (o.GetGoogleServiceAccount() != "" ) { - // emptyGoogleserviceaccount := "" - - o2.SetGoogleServiceAccount("") + if o.GetClientSecret() != "" { + o2.SetClientSecret("") + } - } + if o.GetGoogleServiceAccount() != "" { + o2.SetGoogleServiceAccount("") + } return &o2 } diff --git a/lib/auth/oidc.go b/lib/auth/oidc.go index eb79323e3df32..65f79cde76b4f 100644 --- a/lib/auth/oidc.go +++ b/lib/auth/oidc.go @@ -835,45 +835,41 @@ func (a *Server) getClaims(oidcClient *oidc.Client, connector services.OIDCConne return nil, trace.Wrap(err) } - var config *jwt.Config + var config *jwt.Config var jsonCredentials []byte + //load the google service account uri from + if connector.GetGoogleServiceAccountURI() != "" { - //load the google service account uri from - if(connector.GetGoogleServiceAccountURI()!="") { + serviceAccountURI := connector.GetGoogleServiceAccountURI() + if serviceAccountURI == "" { + return nil, trace.NotFound( + "the google workspace connector requires google_service_account_uri parameter to be specified and pointing to a valid google service account file with credentials, read this article for more details https://developers.google.com/admin-sdk/directory/v1/guides/delegation") + } - serviceAccountURI := connector.GetGoogleServiceAccountURI() - if serviceAccountURI == "" { - return nil, trace.NotFound( - "the google workspace connector requires google_service_account_uri parameter to be specified and pointing to a valid google service account file with credentials, read this article for more details https://developers.google.com/admin-sdk/directory/v1/guides/delegation") - } + uri, err := utils.ParseSessionsURI(serviceAccountURI) + if err != nil { + return nil, trace.BadParameter("failed to parse google_service_account_uri: %v", err) + } + jsonCredentials, err = ioutil.ReadFile(uri.Path) + if err != nil { + return nil, trace.Wrap(err) + } - uri, err := utils.ParseSessionsURI(serviceAccountURI) - if err != nil { - return nil, trace.BadParameter("failed to parse google_service_account_uri: %v", err) + } else if connector.GetGoogleServiceAccount() != "" { + + jsonCredentials = []byte(connector.GetGoogleServiceAccount()) } - jsonCredentials, err = ioutil.ReadFile(uri.Path) + + config, err = google.JWTConfigFromJSON(jsonCredentials, teleport.GSuiteGroupsScope) if err != nil { - return nil, trace.Wrap(err) + return nil, trace.BadParameter("unable to parse client secret file to config: %v", err) } - } else if(connector.GetGoogleServiceAccount()!="") { - - jsonCredentials = []byte(connector.GetGoogleServiceAccount()) - } - - config, err = google.JWTConfigFromJSON(jsonCredentials, teleport.GSuiteGroupsScope) - if err != nil { - return nil, trace.BadParameter("unable to parse client secret file to config: %v", err) - } - - - impersonateAdmin := connector.GetGoogleAdminEmail() - if impersonateAdmin == "" { - return nil, trace.NotFound( - "the google workspace connector requires google_admin_email user to impersonate, as service accounts can not be used directly https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority") - } - - + impersonateAdmin := connector.GetGoogleAdminEmail() + if impersonateAdmin == "" { + return nil, trace.NotFound( + "the google workspace connector requires google_admin_email user to impersonate, as service accounts can not be used directly https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority") + } // User should impersonate admin user, otherwise it won't work: // diff --git a/lib/services/local/users.go b/lib/services/local/users.go index 38e151cd46df4..a722e7e605ff4 100644 --- a/lib/services/local/users.go +++ b/lib/services/local/users.go @@ -705,9 +705,9 @@ func (s *IdentityService) GetOIDCConnector(name string, withSecrets bool) (servi } if !withSecrets { conn.SetClientSecret("") - if(conn.GetGoogleServiceAccount() != "") { - conn.SetGoogleServiceAccount("") - } + if conn.GetGoogleServiceAccount() != "" { + conn.SetGoogleServiceAccount("") + } } return conn, nil } @@ -728,9 +728,9 @@ func (s *IdentityService) GetOIDCConnectors(withSecrets bool) ([]services.OIDCCo } if !withSecrets { conn.SetClientSecret("") - if(conn.GetGoogleServiceAccount() != "") { - conn.SetGoogleServiceAccount("") - } + if conn.GetGoogleServiceAccount() != "" { + conn.SetGoogleServiceAccount("") + } } connectors[i] = conn } diff --git a/lib/services/oidc.go b/lib/services/oidc.go index 6c2e5e94a31d4..dc141b5881ead 100644 --- a/lib/services/oidc.go +++ b/lib/services/oidc.go @@ -39,11 +39,9 @@ func ValidateOIDCConnector(oc types.OIDCConnector) error { return trace.BadParameter("RedirectURL: bad url: '%v'", oc.GetRedirectURL()) } - - - if ( (oc.GetGoogleServiceAccountURI() != "") && (oc.GetGoogleServiceAccount() != "") ) { - return trace.BadParameter("google_service_account_uri or google_service_account is supported, not both") - } + if (oc.GetGoogleServiceAccountURI() != "") && (oc.GetGoogleServiceAccount() != "") { + return trace.BadParameter("google_service_account_uri or google_service_account is supported, not both") + } if oc.GetGoogleServiceAccountURI() != "" { uri, err := utils.ParseSessionsURI(oc.GetGoogleServiceAccountURI()) From afe56aba1252017c8dc4b243b3e8eebd1474fad1 Mon Sep 17 00:00:00 2001 From: Steven Martin Date: Tue, 16 Feb 2021 11:22:17 -0500 Subject: [PATCH 03/22] change comment Co-authored-by: Gus Luxton --- api/types/oidc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/types/oidc.go b/api/types/oidc.go index 44c13c85f7633..2ac18d3594c24 100644 --- a/api/types/oidc.go +++ b/api/types/oidc.go @@ -432,7 +432,7 @@ type OIDCConnectorSpecV2 struct { ClaimsToRoles []ClaimMapping `json:"claims_to_roles,omitempty"` // GoogleServiceAccountURI is a path to google service account uri GoogleServiceAccountURI string `json:"google_service_account_uri,omitempty"` - // GoogleServiceAccount is the contents of the google service account credentials + // GoogleServiceAccount is a string containing the google service account credentials GoogleServiceAccount string `json:"google_service_account,omitempty"` // GoogleAdminEmail is email of google admin to impersonate From 4f23afd2a1cb92ccfd93bd61a0363f33f22a3fc0 Mon Sep 17 00:00:00 2001 From: Steven Martin Date: Tue, 16 Feb 2021 11:23:21 -0500 Subject: [PATCH 04/22] spacing Co-authored-by: Gus Luxton --- lib/services/oidc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/oidc.go b/lib/services/oidc.go index dc141b5881ead..4e6dfe8daa86d 100644 --- a/lib/services/oidc.go +++ b/lib/services/oidc.go @@ -105,7 +105,7 @@ var OIDCConnectorSpecV2Schema = fmt.Sprintf(`{ "display": {"type": "string"}, "prompt": {"type": "string"}, "google_service_account_uri": {"type": "string"}, - "google_service_account": {"type": "string"}, + "google_service_account": {"type": "string"}, "google_admin_email": {"type": "string"}, "scope": { "type": "array", From b4f119410db4421b950b8df2fe0549d24b73ad3d Mon Sep 17 00:00:00 2001 From: Steven Martin Date: Tue, 16 Feb 2021 11:25:25 -0500 Subject: [PATCH 05/22] change comment for googleserviceaccount Co-authored-by: Gus Luxton --- api/types/oidc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/types/oidc.go b/api/types/oidc.go index 2ac18d3594c24..5d117df71aa8c 100644 --- a/api/types/oidc.go +++ b/api/types/oidc.go @@ -148,7 +148,7 @@ func (o *OIDCConnectorV2) GetGoogleServiceAccount() string { return o.Spec.GoogleServiceAccount } -// SetResourceID sets resource ID +// SetGoogleServiceAccount sets a string representing a Google service account func (o *OIDCConnectorV2) SetGoogleServiceAccount(s string) { o.Spec.GoogleServiceAccount = s } From bd9379250ce8a832a141899f0054e2d79e068d3c Mon Sep 17 00:00:00 2001 From: Steven Martin Date: Tue, 16 Feb 2021 11:26:21 -0500 Subject: [PATCH 06/22] correct comment Co-authored-by: Gus Luxton --- lib/auth/oidc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/auth/oidc.go b/lib/auth/oidc.go index 65f79cde76b4f..7c4936146a655 100644 --- a/lib/auth/oidc.go +++ b/lib/auth/oidc.go @@ -837,7 +837,7 @@ func (a *Server) getClaims(oidcClient *oidc.Client, connector services.OIDCConne var config *jwt.Config var jsonCredentials []byte - //load the google service account uri from + // load the google service account from uri if connector.GetGoogleServiceAccountURI() != "" { serviceAccountURI := connector.GetGoogleServiceAccountURI() From 7fd9216f48c239caefa647ca259cca7cccb5d642 Mon Sep 17 00:00:00 2001 From: Steven Martin Date: Tue, 16 Feb 2021 11:26:53 -0500 Subject: [PATCH 07/22] modify comment on GetGoogleServiceAccount Co-authored-by: Gus Luxton --- api/types/oidc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/types/oidc.go b/api/types/oidc.go index 5d117df71aa8c..65c9fbc205a24 100644 --- a/api/types/oidc.go +++ b/api/types/oidc.go @@ -143,7 +143,7 @@ func (o *OIDCConnectorV2) GetGoogleServiceAccountURI() string { return o.Spec.GoogleServiceAccountURI } -// GetGoogleServiceAccountURI returns an optional path to google service account file +// GetGoogleServiceAccount returns a string representing a Google service account func (o *OIDCConnectorV2) GetGoogleServiceAccount() string { return o.Spec.GoogleServiceAccount } From 0eda340b7c70c954510cefaeddda50b7e7e323ab Mon Sep 17 00:00:00 2001 From: Steven Martin Date: Tue, 16 Feb 2021 11:48:28 -0500 Subject: [PATCH 08/22] add comment on loading google service account Co-authored-by: Gus Luxton --- lib/auth/oidc.go | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/auth/oidc.go b/lib/auth/oidc.go index 7c4936146a655..ff57faf531484 100644 --- a/lib/auth/oidc.go +++ b/lib/auth/oidc.go @@ -855,6 +855,7 @@ func (a *Server) getClaims(oidcClient *oidc.Client, connector services.OIDCConne return nil, trace.Wrap(err) } + // load the google service account from string } else if connector.GetGoogleServiceAccount() != "" { jsonCredentials = []byte(connector.GetGoogleServiceAccount()) From fff0251be11bc9b944e1a42ab2d4b616815a6ca7 Mon Sep 17 00:00:00 2001 From: stevenGravy Date: Tue, 16 Feb 2021 11:50:14 -0500 Subject: [PATCH 09/22] Moved comments to correct line and modified language --- api/types/oidc.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/api/types/oidc.go b/api/types/oidc.go index 65c9fbc205a24..d39d34891efef 100644 --- a/api/types/oidc.go +++ b/api/types/oidc.go @@ -85,13 +85,13 @@ type OIDCConnector interface { SetDisplay(string) // GetGoogleServiceAccountURI returns path to google service account URI GetGoogleServiceAccountURI() string - // GetGoogleAdminEmail returns a google admin user email - // https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority - // "Note: Although you can use service accounts in applications that run from a G Suite domain, service accounts are not members of your G Suite account and aren’t subject to domain policies set by G Suite administrators. For example, a policy set in the G Suite admin console to restrict the ability of G Suite end users to share documents outside of the domain would not apply to service accounts." + // GetGoogleServiceAccount returns google service account json for Google GetGoogleServiceAccount() string - // GetGoogleServiceAccount retrieves service account json for Google + // SetGoogleServiceAccount sets the google service account json contents SetGoogleServiceAccount(string) - // sets the service account json for Google + // GetGoogleAdminEmail returns a google admin user email + // https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority + // "Note: Although you can use service accounts in applications that run from a Googke Worksapace (formerly G Suite) domain, service accounts are not members of your Google Workspace account and aren’t subject to domain policies set by administrators. For example, a policy set in the Google Workspace admin console to restrict the ability of G Suite end users to share documents outside of the domain would not apply to service accounts." GetGoogleAdminEmail() string } From 46f089f98a2138598bfcdb9f6b533633f74e6621 Mon Sep 17 00:00:00 2001 From: Steven Martin Date: Tue, 16 Feb 2021 12:03:35 -0500 Subject: [PATCH 10/22] lint fix From 6db19d1fa2bccb53a13bda02c589a51ef50862ad Mon Sep 17 00:00:00 2001 From: stevenGravy Date: Tue, 16 Feb 2021 12:30:43 -0500 Subject: [PATCH 11/22] added credential loading method variable for better error reporting when using google service account uri or inline. --- lib/auth/oidc.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/auth/oidc.go b/lib/auth/oidc.go index ff57faf531484..0c74e3df46e9e 100644 --- a/lib/auth/oidc.go +++ b/lib/auth/oidc.go @@ -837,9 +837,10 @@ func (a *Server) getClaims(oidcClient *oidc.Client, connector services.OIDCConne var config *jwt.Config var jsonCredentials []byte + var credentialLoadingMethod string // load the google service account from uri if connector.GetGoogleServiceAccountURI() != "" { - + credentialLoadingMethod = "google_service_account_uri" serviceAccountURI := connector.GetGoogleServiceAccountURI() if serviceAccountURI == "" { return nil, trace.NotFound( @@ -855,15 +856,15 @@ func (a *Server) getClaims(oidcClient *oidc.Client, connector services.OIDCConne return nil, trace.Wrap(err) } - // load the google service account from string + // load the google service account from string } else if connector.GetGoogleServiceAccount() != "" { - + credentialLoadingMethod = "google_service_account" jsonCredentials = []byte(connector.GetGoogleServiceAccount()) } config, err = google.JWTConfigFromJSON(jsonCredentials, teleport.GSuiteGroupsScope) if err != nil { - return nil, trace.BadParameter("unable to parse client secret file to config: %v", err) + return nil, trace.BadParameter("unable to parse google service account from %v: %v", credentialLoadingMethod, err) } impersonateAdmin := connector.GetGoogleAdminEmail() From 5bced25adbe5bea14460666db26d16736948780b Mon Sep 17 00:00:00 2001 From: stevenGravy Date: Tue, 16 Feb 2021 13:35:34 -0500 Subject: [PATCH 12/22] modified debug message to use variable name while giving google workspace context --- lib/auth/oidc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/auth/oidc.go b/lib/auth/oidc.go index 0c74e3df46e9e..71a078fdf95c2 100644 --- a/lib/auth/oidc.go +++ b/lib/auth/oidc.go @@ -893,7 +893,7 @@ func (a *Server) getClaims(oidcClient *oidc.Client, connector services.OIDCConne log.Debugf("Found no Google Workspace claims.") } else { if gsuiteClaims != nil { - log.Debugf("Got GoogleWorkspace claims: %v.", gsuiteClaims) + log.Debugf("Got gsuiteClaims claims from Google Workspace: %v.", gsuiteClaims) } claims, err = mergeClaims(claims, gsuiteClaims) if err != nil { From 5bc53c209f308cc252619e232efca2cf10987b19 Mon Sep 17 00:00:00 2001 From: Steven Martin Date: Tue, 16 Feb 2021 20:01:09 -0500 Subject: [PATCH 13/22] take out unnecessary if check Co-authored-by: Andrew Lytvynov --- api/types/oidc.go | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/api/types/oidc.go b/api/types/oidc.go index d39d34891efef..f78d63bd1882d 100644 --- a/api/types/oidc.go +++ b/api/types/oidc.go @@ -195,13 +195,8 @@ func (o *OIDCConnectorV2) WithoutSecrets() Resource { } o2 := *o - if o.GetClientSecret() != "" { - o2.SetClientSecret("") - } - - if o.GetGoogleServiceAccount() != "" { - o2.SetGoogleServiceAccount("") - } + o2.SetClientSecret("") + o2.SetGoogleServiceAccount("") return &o2 } From fe843660356b68ae2b83b078b55151756446c01b Mon Sep 17 00:00:00 2001 From: Steven Martin Date: Tue, 16 Feb 2021 20:03:01 -0500 Subject: [PATCH 14/22] better error message handling Co-authored-by: Andrew Lytvynov --- lib/auth/oidc.go | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/lib/auth/oidc.go b/lib/auth/oidc.go index 71a078fdf95c2..7b81307c1ac7f 100644 --- a/lib/auth/oidc.go +++ b/lib/auth/oidc.go @@ -835,19 +835,13 @@ func (a *Server) getClaims(oidcClient *oidc.Client, connector services.OIDCConne return nil, trace.Wrap(err) } - var config *jwt.Config var jsonCredentials []byte var credentialLoadingMethod string - // load the google service account from uri if connector.GetGoogleServiceAccountURI() != "" { + // load the google service account from URI credentialLoadingMethod = "google_service_account_uri" - serviceAccountURI := connector.GetGoogleServiceAccountURI() - if serviceAccountURI == "" { - return nil, trace.NotFound( - "the google workspace connector requires google_service_account_uri parameter to be specified and pointing to a valid google service account file with credentials, read this article for more details https://developers.google.com/admin-sdk/directory/v1/guides/delegation") - } - uri, err := utils.ParseSessionsURI(serviceAccountURI) + uri, err := utils.ParseSessionsURI(connector.GetGoogleServiceAccountURI()) if err != nil { return nil, trace.BadParameter("failed to parse google_service_account_uri: %v", err) } @@ -855,11 +849,13 @@ func (a *Server) getClaims(oidcClient *oidc.Client, connector services.OIDCConne if err != nil { return nil, trace.Wrap(err) } - - // load the google service account from string } else if connector.GetGoogleServiceAccount() != "" { + // load the google service account from string credentialLoadingMethod = "google_service_account" jsonCredentials = []byte(connector.GetGoogleServiceAccount()) + } else { + return nil, trace.NotFound( + "the google workspace connector requires google_service_account parameter with JSON-formatted credentials or google_service_account_uri parameter pointing to a valid google service account file with credentials to be specified, read this article for more details https://developers.google.com/admin-sdk/directory/v1/guides/delegation") } config, err = google.JWTConfigFromJSON(jsonCredentials, teleport.GSuiteGroupsScope) From 8ff363018e154ef34482cafb7f3fcb107d040f2e Mon Sep 17 00:00:00 2001 From: Steven Martin Date: Tue, 16 Feb 2021 20:03:20 -0500 Subject: [PATCH 15/22] config assignment Co-authored-by: Andrew Lytvynov --- lib/auth/oidc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/auth/oidc.go b/lib/auth/oidc.go index 7b81307c1ac7f..801a3be2aa5eb 100644 --- a/lib/auth/oidc.go +++ b/lib/auth/oidc.go @@ -858,7 +858,7 @@ func (a *Server) getClaims(oidcClient *oidc.Client, connector services.OIDCConne "the google workspace connector requires google_service_account parameter with JSON-formatted credentials or google_service_account_uri parameter pointing to a valid google service account file with credentials to be specified, read this article for more details https://developers.google.com/admin-sdk/directory/v1/guides/delegation") } - config, err = google.JWTConfigFromJSON(jsonCredentials, teleport.GSuiteGroupsScope) + config, err := google.JWTConfigFromJSON(jsonCredentials, teleport.GSuiteGroupsScope) if err != nil { return nil, trace.BadParameter("unable to parse google service account from %v: %v", credentialLoadingMethod, err) } From 286e61c6e628619c7edf585a1844053d6511b230 Mon Sep 17 00:00:00 2001 From: Steven Martin Date: Tue, 16 Feb 2021 20:03:37 -0500 Subject: [PATCH 16/22] remove unnecessary if check Co-authored-by: Andrew Lytvynov --- lib/services/local/users.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/services/local/users.go b/lib/services/local/users.go index 7b81fa61a7960..de8c021e6ad4d 100644 --- a/lib/services/local/users.go +++ b/lib/services/local/users.go @@ -741,9 +741,7 @@ func (s *IdentityService) GetOIDCConnectors(withSecrets bool) ([]services.OIDCCo } if !withSecrets { conn.SetClientSecret("") - if conn.GetGoogleServiceAccount() != "" { - conn.SetGoogleServiceAccount("") - } + conn.SetGoogleServiceAccount("") } connectors[i] = conn } From 59f9396e1186e2dcb8a0be71965b3c70c82f14b9 Mon Sep 17 00:00:00 2001 From: Steven Martin Date: Tue, 16 Feb 2021 20:04:07 -0500 Subject: [PATCH 17/22] remove unnecessary parenthesis Co-authored-by: Andrew Lytvynov --- lib/services/oidc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/oidc.go b/lib/services/oidc.go index 4e6dfe8daa86d..fad6e7ddb0cbb 100644 --- a/lib/services/oidc.go +++ b/lib/services/oidc.go @@ -39,7 +39,7 @@ func ValidateOIDCConnector(oc types.OIDCConnector) error { return trace.BadParameter("RedirectURL: bad url: '%v'", oc.GetRedirectURL()) } - if (oc.GetGoogleServiceAccountURI() != "") && (oc.GetGoogleServiceAccount() != "") { + if oc.GetGoogleServiceAccountURI() != "" && oc.GetGoogleServiceAccount() != "" { return trace.BadParameter("google_service_account_uri or google_service_account is supported, not both") } From 29823959bd3f8ad37a34c008277b960e296f38d6 Mon Sep 17 00:00:00 2001 From: Steven Martin Date: Tue, 16 Feb 2021 20:04:24 -0500 Subject: [PATCH 18/22] spacing for variable Co-authored-by: Andrew Lytvynov --- lib/services/oidc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/oidc.go b/lib/services/oidc.go index fad6e7ddb0cbb..f64ecc8fca1d9 100644 --- a/lib/services/oidc.go +++ b/lib/services/oidc.go @@ -105,7 +105,7 @@ var OIDCConnectorSpecV2Schema = fmt.Sprintf(`{ "display": {"type": "string"}, "prompt": {"type": "string"}, "google_service_account_uri": {"type": "string"}, - "google_service_account": {"type": "string"}, + "google_service_account": {"type": "string"}, "google_admin_email": {"type": "string"}, "scope": { "type": "array", From df063a624507b43e630e56db88e8860337a7b316 Mon Sep 17 00:00:00 2001 From: Steven Martin Date: Tue, 16 Feb 2021 20:04:47 -0500 Subject: [PATCH 19/22] remove unnecessary if check Co-authored-by: Andrew Lytvynov --- lib/services/local/users.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/services/local/users.go b/lib/services/local/users.go index de8c021e6ad4d..2724bdcad0861 100644 --- a/lib/services/local/users.go +++ b/lib/services/local/users.go @@ -718,9 +718,7 @@ func (s *IdentityService) GetOIDCConnector(name string, withSecrets bool) (servi } if !withSecrets { conn.SetClientSecret("") - if conn.GetGoogleServiceAccount() != "" { - conn.SetGoogleServiceAccount("") - } + conn.SetGoogleServiceAccount("") } return conn, nil } From 96b20fb6e6d2cf94ee8047b5dadc93f62ba1b8d8 Mon Sep 17 00:00:00 2001 From: stevenGravy Date: Tue, 16 Feb 2021 20:07:18 -0500 Subject: [PATCH 20/22] lint fix --- lib/auth/oidc.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/auth/oidc.go b/lib/auth/oidc.go index 801a3be2aa5eb..52d340c94f922 100644 --- a/lib/auth/oidc.go +++ b/lib/auth/oidc.go @@ -854,8 +854,7 @@ func (a *Server) getClaims(oidcClient *oidc.Client, connector services.OIDCConne credentialLoadingMethod = "google_service_account" jsonCredentials = []byte(connector.GetGoogleServiceAccount()) } else { - return nil, trace.NotFound( - "the google workspace connector requires google_service_account parameter with JSON-formatted credentials or google_service_account_uri parameter pointing to a valid google service account file with credentials to be specified, read this article for more details https://developers.google.com/admin-sdk/directory/v1/guides/delegation") + return nil, trace.NotFound("the google workspace connector requires google_service_account parameter with JSON-formatted credentials or google_service_account_uri parameter pointing to a valid google service account file with credentials to be specified, read this article for more details https://developers.google.com/admin-sdk/directory/v1/guides/delegation") } config, err := google.JWTConfigFromJSON(jsonCredentials, teleport.GSuiteGroupsScope) From 936ce88221bbd4390e2256c30a72553ddcb0f21e Mon Sep 17 00:00:00 2001 From: Steven Martin Date: Wed, 17 Feb 2021 14:57:40 -0500 Subject: [PATCH 21/22] Fix language Co-authored-by: Gus Luxton --- api/types/oidc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/types/oidc.go b/api/types/oidc.go index f78d63bd1882d..dca988fbcab3a 100644 --- a/api/types/oidc.go +++ b/api/types/oidc.go @@ -91,7 +91,7 @@ type OIDCConnector interface { SetGoogleServiceAccount(string) // GetGoogleAdminEmail returns a google admin user email // https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority - // "Note: Although you can use service accounts in applications that run from a Googke Worksapace (formerly G Suite) domain, service accounts are not members of your Google Workspace account and aren’t subject to domain policies set by administrators. For example, a policy set in the Google Workspace admin console to restrict the ability of G Suite end users to share documents outside of the domain would not apply to service accounts." + // "Note: Although you can use service accounts in applications that run from a Google Workspace (formerly G Suite) domain, service accounts are not members of your Google Workspace account and aren’t subject to domain policies set by administrators. For example, a policy set in the Google Workspace admin console to restrict the ability of end users to share documents outside of the domain would not apply to service accounts." GetGoogleAdminEmail() string } From 3d08355bb6f4144bd639bca282d504daf18d18f3 Mon Sep 17 00:00:00 2001 From: Steven Martin Date: Wed, 17 Feb 2021 14:57:55 -0500 Subject: [PATCH 22/22] language change Co-authored-by: Gus Luxton --- lib/services/oidc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/services/oidc.go b/lib/services/oidc.go index f64ecc8fca1d9..1316ae0bd3328 100644 --- a/lib/services/oidc.go +++ b/lib/services/oidc.go @@ -40,7 +40,7 @@ func ValidateOIDCConnector(oc types.OIDCConnector) error { } if oc.GetGoogleServiceAccountURI() != "" && oc.GetGoogleServiceAccount() != "" { - return trace.BadParameter("google_service_account_uri or google_service_account is supported, not both") + return trace.BadParameter("one of either google_service_account_uri or google_service_account is supported, not both") } if oc.GetGoogleServiceAccountURI() != "" {