15348: Look up hostname if not provided in config args.
authorTom Clegg <tom@tomclegg.ca>
Thu, 2 Jul 2020 14:48:15 +0000 (10:48 -0400)
committerTom Clegg <tom@tomclegg.ca>
Thu, 2 Jul 2020 14:48:15 +0000 (10:48 -0400)
Arvados-DCO-1.1-Signed-off-by: Tom Clegg <tom@tomclegg.ca>

lib/pam/README
lib/pam/docker_test.go
lib/pam/pam_arvados.go

index 243a179e6c4227a7b8f87cbe77b9194ba3c01de8..aafff23a8cb963b11d79cefcfa21ae7f6aff0fb5 100644 (file)
@@ -1 +1,18 @@
 For configuration advice, please refer to https://doc.arvados.org/install/install-webshell.html
+
+Usage (in pam config):
+
+    pam_arvados.so arvados_api_host [my_vm_host_name] ["insecure"] ["debug"]
+
+pam_arvados.so passes authentication if (according to
+arvados_api_host) the supplied PAM token belongs to an Arvados user
+who is allowed to log in to my_vm_host_name with the supplied PAM
+username.
+
+If my_vm_host_name is omitted or "-", the current hostname is used.
+
+"insecure" -- continue even if the TLS certificate presented by
+arvados_api_host fails verification.
+
+"debug" -- enable debug-level log messages in syslog and (when not in
+"silent" mode) on the calling application's stderr.
index 5b1755496b66089cfd97e57b34bc4d679192d060..fa16b313beaed8b66b9f1544d148a30c05b78f83 100644 (file)
@@ -60,7 +60,6 @@ func (s *DockerSuite) SetUpSuite(c *check.C) {
        }
        s.proxysrv = &http.Server{Handler: proxy}
        go s.proxysrv.ServeTLS(ln, "../../services/api/tmp/self-signed.pem", "../../services/api/tmp/self-signed.key")
-       proxyhost := ln.Addr().String()
 
        // Build a pam module to install & configure in the docker
        // container.
@@ -70,20 +69,6 @@ func (s *DockerSuite) SetUpSuite(c *check.C) {
        err = cmd.Run()
        c.Assert(err, check.IsNil)
 
-       // Write a PAM config file that uses our proxy as
-       // ARVADOS_API_HOST.
-       confdata := fmt.Sprintf(`Name: Arvados authentication
-Default: yes
-Priority: 256
-Auth-Type: Primary
-Auth:
-       [success=end default=ignore]    /usr/lib/pam_arvados.so %s testvm2.shell insecure
-Auth-Initial:
-       [success=end default=ignore]    /usr/lib/pam_arvados.so %s testvm2.shell insecure
-`, proxyhost, proxyhost)
-       err = ioutil.WriteFile(s.tmpdir+"/conffile", []byte(confdata), 0755)
-       c.Assert(err, check.IsNil)
-
        // Build the testclient program that will (from inside the
        // docker container) configure the system to use the above PAM
        // config, and then try authentication.
@@ -103,9 +88,28 @@ func (s *DockerSuite) TearDownSuite(c *check.C) {
        }
 }
 
+func (s *DockerSuite) SetUpTest(c *check.C) {
+       // Write a PAM config file that uses our proxy as
+       // ARVADOS_API_HOST.
+       proxyhost := s.proxyln.Addr().String()
+       confdata := fmt.Sprintf(`Name: Arvados authentication
+Default: yes
+Priority: 256
+Auth-Type: Primary
+Auth:
+       [success=end default=ignore]    /usr/lib/pam_arvados.so %s testvm2.shell insecure
+Auth-Initial:
+       [success=end default=ignore]    /usr/lib/pam_arvados.so %s testvm2.shell insecure
+`, proxyhost, proxyhost)
+       err := ioutil.WriteFile(s.tmpdir+"/conffile", []byte(confdata), 0755)
+       c.Assert(err, check.IsNil)
+}
+
 func (s *DockerSuite) runTestClient(c *check.C, args ...string) (stdout, stderr *bytes.Buffer, err error) {
+
        cmd := exec.Command("docker", append([]string{
                "run", "--rm",
+               "--hostname", "testvm2.shell",
                "--add-host", "zzzzz.arvadosapi.com:" + s.hostip,
                "-v", s.tmpdir + "/pam_arvados.so:/usr/lib/pam_arvados.so:ro",
                "-v", s.tmpdir + "/conffile:/usr/share/pam-configs/arvados:ro",
@@ -147,3 +151,23 @@ func (s *DockerSuite) TestFailure(c *check.C) {
                c.Check(stderr.String(), check.Matches, `(?ms).*authentication failed.*`)
        }
 }
+
+func (s *DockerSuite) TestDefaultHostname(c *check.C) {
+       confdata := fmt.Sprintf(`Name: Arvados authentication
+Default: yes
+Priority: 256
+Auth-Type: Primary
+Auth:
+       [success=end default=ignore]    /usr/lib/pam_arvados.so %s - insecure debug
+Auth-Initial:
+       [success=end default=ignore]    /usr/lib/pam_arvados.so %s - insecure debug
+`, s.proxyln.Addr().String(), s.proxyln.Addr().String())
+       err := ioutil.WriteFile(s.tmpdir+"/conffile", []byte(confdata), 0755)
+       c.Assert(err, check.IsNil)
+
+       stdout, stderr, err := s.runTestClient(c, "try", "active", arvadostest.ActiveTokenV2)
+       c.Check(err, check.IsNil)
+       c.Logf("%s", stderr.String())
+       c.Check(stdout.String(), check.Equals, "")
+       c.Check(stderr.String(), check.Matches, `(?ms).*authentication succeeded.*`)
+}
index 389033ba963575fb8c4e7b50054c95cb05bab211..34b90805363fc3230ef7f78f1bf3605ecebdfdea 100644 (file)
@@ -24,6 +24,7 @@ package main
 import (
        "io/ioutil"
        "log/syslog"
+       "os"
 
        "context"
        "errors"
@@ -104,8 +105,16 @@ func authenticate(logger *logrus.Logger, username, token string, argv []string)
                        logger.Warnf("unkown option: %s\n", arg)
                }
        }
+       if hostname == "" || hostname == "-" {
+               h, err := os.Hostname()
+               if err != nil {
+                       logger.WithError(err).Warnf("cannot get hostname -- try using an explicit hostname in pam config")
+                       return fmt.Errorf("cannot get hostname: %w", err)
+               }
+               hostname = h
+       }
        logger.Debugf("username=%q arvados_api_host=%q hostname=%q insecure=%t", username, apiHost, hostname, insecure)
-       if apiHost == "" || hostname == "" {
+       if apiHost == "" {
                logger.Warnf("cannot authenticate: config error: arvados_api_host and hostname must be non-empty")
                return errors.New("config error")
        }