[ARVADOS] updated: 2.1.0-17-g504fc7b60

Git user git at public.arvados.org
Mon Oct 19 19:05:38 UTC 2020


Summary of changes:
 lib/controller/federation/conn.go                  | 40 ++++++++++++++++++++--
 lib/controller/localdb/conn.go                     |  6 ++--
 lib/controller/localdb/login.go                    | 18 +++++-----
 lib/controller/localdb/login_ldap.go               |  6 ++--
 lib/controller/localdb/login_oidc.go               |  4 +--
 lib/controller/localdb/login_pam.go                |  6 ++--
 lib/controller/localdb/login_testuser.go           |  6 ++--
 lib/controller/rpc/conn.go                         |  1 +
 .../app/controllers/user_sessions_controller.rb    | 20 +++++++----
 9 files changed, 76 insertions(+), 31 deletions(-)

       via  504fc7b60000d154aa33fbced8f581adb69f953f (commit)
      from  70242f2d84699baee2ea0b6995a447b0ba776c14 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.


commit 504fc7b60000d154aa33fbced8f581adb69f953f
Author: Tom Clegg <tom at tomclegg.ca>
Date:   Mon Oct 19 15:04:22 2020 -0400

    17014: Port container request federation code to new style (WIP).
    
    Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom at tomclegg.ca>

diff --git a/lib/controller/federation/conn.go b/lib/controller/federation/conn.go
index 955d184c5..d1c61116d 100644
--- a/lib/controller/federation/conn.go
+++ b/lib/controller/federation/conn.go
@@ -26,7 +26,7 @@ import (
 
 type Conn struct {
 	cluster *arvados.Cluster
-	local   backend
+	local   *localdb.Conn
 	remotes map[string]backend
 }
 
@@ -333,7 +333,43 @@ func (conn *Conn) ContainerRequestList(ctx context.Context, options arvados.List
 }
 
 func (conn *Conn) ContainerRequestCreate(ctx context.Context, options arvados.CreateOptions) (arvados.ContainerRequest, error) {
-	return conn.chooseBackend(options.ClusterID).ContainerRequestCreate(ctx, options)
+	be := conn.chooseBackend(options.ClusterID)
+	if be == conn.local {
+		return be.ContainerRequestCreate(ctx, options)
+	}
+	if _, ok := options.Attrs["runtime_token"]; !ok {
+		// If runtime_token is not set, create a new token
+		aca, err := conn.local.APIClientAuthorizationCurrent(ctx, arvados.GetOptions{})
+		if err != nil {
+			// This should probably be StatusUnauthorized
+			// (need to update test in
+			// lib/controller/federation_test.go):
+			return arvados.ContainerRequest{}, httpErrorf(http.StatusForbidden, "%w", err)
+		}
+		user, err := conn.local.UserGetCurrent(ctx, arvados.GetOptions{})
+		if err != nil {
+			return arvados.ContainerRequest{}, err
+		}
+		if len(aca.Scopes) != 0 || aca.Scopes[0] != "all" {
+			return arvados.ContainerRequest{}, httpErrorf(http.StatusForbidden, "token scope is not [all]")
+		}
+		if strings.HasPrefix(aca.UUID, conn.cluster.ClusterID) {
+			// Local user, submitting to a remote cluster.
+			// Create a new (FIXME: needs to be
+			// time-limited!) token.
+			aca, err = localdb.CreateAPIClientAuthorization(ctx, conn.local, conn.cluster.SystemRootToken, rpc.UserSessionAuthInfo{UserUUID: user.UUID})
+			if err != nil {
+				return arvados.ContainerRequest{}, err
+			}
+			options.Attrs["runtime_token"] = aca.TokenV2()
+		} else {
+			// Remote user. Container request will use the
+			// current token, minus the trailing portion
+			// (optional container uuid).
+			options.Attrs["runtime_token"] = aca.TokenV2()
+		}
+	}
+	return be.ContainerRequestCreate(ctx, options)
 }
 
 func (conn *Conn) ContainerRequestUpdate(ctx context.Context, options arvados.UpdateOptions) (arvados.ContainerRequest, error) {
diff --git a/lib/controller/localdb/conn.go b/lib/controller/localdb/conn.go
index 4f0035edf..ac120c6f3 100644
--- a/lib/controller/localdb/conn.go
+++ b/lib/controller/localdb/conn.go
@@ -24,10 +24,10 @@ func NewConn(cluster *arvados.Cluster) *Conn {
 	railsProxy := railsproxy.NewConn(cluster)
 	var conn Conn
 	conn = Conn{
-		cluster:         cluster,
-		railsProxy:      railsProxy,
-		loginController: chooseLoginController(cluster, railsProxy),
+		cluster:    cluster,
+		railsProxy: railsProxy,
 	}
+	conn.loginController = chooseLoginController(cluster, &conn)
 	return &conn
 }
 
diff --git a/lib/controller/localdb/login.go b/lib/controller/localdb/login.go
index f4632751e..b14fd3b7d 100644
--- a/lib/controller/localdb/login.go
+++ b/lib/controller/localdb/login.go
@@ -27,7 +27,7 @@ type loginController interface {
 	UserAuthenticate(ctx context.Context, options arvados.UserAuthenticateOptions) (arvados.APIClientAuthorization, error)
 }
 
-func chooseLoginController(cluster *arvados.Cluster, railsProxy *railsProxy) loginController {
+func chooseLoginController(cluster *arvados.Cluster, parent *Conn) loginController {
 	wantGoogle := cluster.Login.Google.Enable
 	wantOpenIDConnect := cluster.Login.OpenIDConnect.Enable
 	wantSSO := cluster.Login.SSO.Enable
@@ -43,7 +43,7 @@ func chooseLoginController(cluster *arvados.Cluster, railsProxy *railsProxy) log
 	case wantGoogle:
 		return &oidcLoginController{
 			Cluster:            cluster,
-			RailsProxy:         railsProxy,
+			Parent:             parent,
 			Issuer:             "https://accounts.google.com",
 			ClientID:           cluster.Login.Google.ClientID,
 			ClientSecret:       cluster.Login.Google.ClientSecret,
@@ -54,7 +54,7 @@ func chooseLoginController(cluster *arvados.Cluster, railsProxy *railsProxy) log
 	case wantOpenIDConnect:
 		return &oidcLoginController{
 			Cluster:            cluster,
-			RailsProxy:         railsProxy,
+			Parent:             parent,
 			Issuer:             cluster.Login.OpenIDConnect.Issuer,
 			ClientID:           cluster.Login.OpenIDConnect.ClientID,
 			ClientSecret:       cluster.Login.OpenIDConnect.ClientSecret,
@@ -63,13 +63,13 @@ func chooseLoginController(cluster *arvados.Cluster, railsProxy *railsProxy) log
 			UsernameClaim:      cluster.Login.OpenIDConnect.UsernameClaim,
 		}
 	case wantSSO:
-		return &ssoLoginController{railsProxy}
+		return &ssoLoginController{parent}
 	case wantPAM:
-		return &pamLoginController{Cluster: cluster, RailsProxy: railsProxy}
+		return &pamLoginController{Cluster: cluster, Parent: parent}
 	case wantLDAP:
-		return &ldapLoginController{Cluster: cluster, RailsProxy: railsProxy}
+		return &ldapLoginController{Cluster: cluster, Parent: parent}
 	case wantTest:
-		return &testLoginController{Cluster: cluster, RailsProxy: railsProxy}
+		return &testLoginController{Cluster: cluster, Parent: parent}
 	case wantLoginCluster:
 		return &federatedLoginController{Cluster: cluster}
 	default:
@@ -91,7 +91,7 @@ func countTrue(vals ...bool) int {
 
 // Login and Logout are passed through to the wrapped railsProxy;
 // UserAuthenticate is rejected.
-type ssoLoginController struct{ *railsProxy }
+type ssoLoginController struct{ *Conn }
 
 func (ctrl *ssoLoginController) UserAuthenticate(ctx context.Context, opts arvados.UserAuthenticateOptions) (arvados.APIClientAuthorization, error) {
 	return arvados.APIClientAuthorization{}, httpserver.ErrorWithStatus(errors.New("username/password authentication is not available"), http.StatusBadRequest)
@@ -135,7 +135,7 @@ func noopLogout(cluster *arvados.Cluster, opts arvados.LogoutOptions) (arvados.L
 	return arvados.LogoutResponse{RedirectLocation: target}, nil
 }
 
-func createAPIClientAuthorization(ctx context.Context, conn *rpc.Conn, rootToken string, authinfo rpc.UserSessionAuthInfo) (resp arvados.APIClientAuthorization, err error) {
+func CreateAPIClientAuthorization(ctx context.Context, conn *Conn, rootToken string, authinfo rpc.UserSessionAuthInfo) (resp arvados.APIClientAuthorization, err error) {
 	ctxRoot := auth.NewContext(ctx, &auth.Credentials{Tokens: []string{rootToken}})
 	newsession, err := conn.UserSessionCreate(ctxRoot, rpc.UserSessionCreateOptions{
 		// Send a fake ReturnTo value instead of the caller's
diff --git a/lib/controller/localdb/login_ldap.go b/lib/controller/localdb/login_ldap.go
index 6c430d69b..a03082e30 100644
--- a/lib/controller/localdb/login_ldap.go
+++ b/lib/controller/localdb/login_ldap.go
@@ -21,8 +21,8 @@ import (
 )
 
 type ldapLoginController struct {
-	Cluster    *arvados.Cluster
-	RailsProxy *railsProxy
+	Cluster *arvados.Cluster
+	Parent  *Conn
 }
 
 func (ctrl *ldapLoginController) Logout(ctx context.Context, opts arvados.LogoutOptions) (arvados.LogoutResponse, error) {
@@ -143,7 +143,7 @@ func (ctrl *ldapLoginController) UserAuthenticate(ctx context.Context, opts arva
 		return arvados.APIClientAuthorization{}, errors.New("authentication succeeded but ldap returned no email address")
 	}
 
-	return createAPIClientAuthorization(ctx, ctrl.RailsProxy, ctrl.Cluster.SystemRootToken, rpc.UserSessionAuthInfo{
+	return CreateAPIClientAuthorization(ctx, ctrl.Parent, ctrl.Cluster.SystemRootToken, rpc.UserSessionAuthInfo{
 		Email:     email,
 		FirstName: attrs["givenname"],
 		LastName:  attrs["sn"],
diff --git a/lib/controller/localdb/login_oidc.go b/lib/controller/localdb/login_oidc.go
index e0b01f13e..d82b2adb2 100644
--- a/lib/controller/localdb/login_oidc.go
+++ b/lib/controller/localdb/login_oidc.go
@@ -32,7 +32,7 @@ import (
 
 type oidcLoginController struct {
 	Cluster            *arvados.Cluster
-	RailsProxy         *railsProxy
+	Parent             *Conn
 	Issuer             string // OIDC issuer URL, e.g., "https://accounts.google.com"
 	ClientID           string
 	ClientSecret       string
@@ -129,7 +129,7 @@ func (ctrl *oidcLoginController) Login(ctx context.Context, opts arvados.LoginOp
 		return loginError(err)
 	}
 	ctxRoot := auth.NewContext(ctx, &auth.Credentials{Tokens: []string{ctrl.Cluster.SystemRootToken}})
-	return ctrl.RailsProxy.UserSessionCreate(ctxRoot, rpc.UserSessionCreateOptions{
+	return ctrl.Parent.UserSessionCreate(ctxRoot, rpc.UserSessionCreateOptions{
 		ReturnTo: state.Remote + "," + state.ReturnTo,
 		AuthInfo: *authinfo,
 	})
diff --git a/lib/controller/localdb/login_pam.go b/lib/controller/localdb/login_pam.go
index 2447713a2..365f91981 100644
--- a/lib/controller/localdb/login_pam.go
+++ b/lib/controller/localdb/login_pam.go
@@ -20,8 +20,8 @@ import (
 )
 
 type pamLoginController struct {
-	Cluster    *arvados.Cluster
-	RailsProxy *railsProxy
+	Cluster *arvados.Cluster
+	Parent  *Conn
 }
 
 func (ctrl *pamLoginController) Logout(ctx context.Context, opts arvados.LogoutOptions) (arvados.LogoutResponse, error) {
@@ -87,7 +87,7 @@ func (ctrl *pamLoginController) UserAuthenticate(ctx context.Context, opts arvad
 		"user":  user,
 		"email": email,
 	}).Debug("pam authentication succeeded")
-	return createAPIClientAuthorization(ctx, ctrl.RailsProxy, ctrl.Cluster.SystemRootToken, rpc.UserSessionAuthInfo{
+	return CreateAPIClientAuthorization(ctx, ctrl.Parent, ctrl.Cluster.SystemRootToken, rpc.UserSessionAuthInfo{
 		Username: user,
 		Email:    email,
 	})
diff --git a/lib/controller/localdb/login_testuser.go b/lib/controller/localdb/login_testuser.go
index 585227352..d07105623 100644
--- a/lib/controller/localdb/login_testuser.go
+++ b/lib/controller/localdb/login_testuser.go
@@ -17,8 +17,8 @@ import (
 )
 
 type testLoginController struct {
-	Cluster    *arvados.Cluster
-	RailsProxy *railsProxy
+	Cluster *arvados.Cluster
+	Parent  *Conn
 }
 
 func (ctrl *testLoginController) Logout(ctx context.Context, opts arvados.LogoutOptions) (arvados.LogoutResponse, error) {
@@ -45,7 +45,7 @@ func (ctrl *testLoginController) UserAuthenticate(ctx context.Context, opts arva
 				"username": username,
 				"email":    user.Email,
 			}).Debug("test authentication succeeded")
-			return createAPIClientAuthorization(ctx, ctrl.RailsProxy, ctrl.Cluster.SystemRootToken, rpc.UserSessionAuthInfo{
+			return CreateAPIClientAuthorization(ctx, ctrl.Parent, ctrl.Cluster.SystemRootToken, rpc.UserSessionAuthInfo{
 				Username: username,
 				Email:    user.Email,
 			})
diff --git a/lib/controller/rpc/conn.go b/lib/controller/rpc/conn.go
index b0987cb46..5ffa66801 100644
--- a/lib/controller/rpc/conn.go
+++ b/lib/controller/rpc/conn.go
@@ -437,6 +437,7 @@ func (conn *Conn) APIClientAuthorizationCurrent(ctx context.Context, options arv
 }
 
 type UserSessionAuthInfo struct {
+	UserUUID        string   `json:"user_uuid"`
 	Email           string   `json:"email"`
 	AlternateEmails []string `json:"alternate_emails"`
 	FirstName       string   `json:"first_name"`
diff --git a/services/api/app/controllers/user_sessions_controller.rb b/services/api/app/controllers/user_sessions_controller.rb
index 8e3c3ac5e..0bf939d08 100644
--- a/services/api/app/controllers/user_sessions_controller.rb
+++ b/services/api/app/controllers/user_sessions_controller.rb
@@ -30,12 +30,20 @@ class UserSessionsController < ApplicationController
       authinfo = request.env['omniauth.auth']['info'].with_indifferent_access
     end
 
-    begin
-      user = User.register(authinfo)
-    rescue => e
-      Rails.logger.warn "User.register error #{e}"
-      Rails.logger.warn "authinfo was #{authinfo.inspect}"
-      return redirect_to login_failure_url
+    if !authinfo['user_uuid'].blank?
+      user = User.find_by_uuid(authinfo['user_uuid'])
+      if !user
+        Rails.logger.warn "Nonexistent user_uuid in authinfo #{authinfo.inspect}"
+        return redirect_to login_failure_url
+      end
+    else
+      begin
+        user = User.register(authinfo)
+      rescue => e
+        Rails.logger.warn "User.register error #{e}"
+        Rails.logger.warn "authinfo was #{authinfo.inspect}"
+        return redirect_to login_failure_url
+      end
     end
 
     # For the benefit of functional and integration tests:

-----------------------------------------------------------------------


hooks/post-receive
-- 




More information about the arvados-commits mailing list