github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/acceptance/compose/gss/psql/gss_test.go (about)

     1  // Copyright 2019 The Cockroach Authors.
     2  //
     3  // Use of this software is governed by the Business Source License
     4  // included in the file licenses/BSL.txt.
     5  //
     6  // As of the Change Date specified in that file, in accordance with
     7  // the Business Source License, use of this software will be governed
     8  // by the Apache License, Version 2.0, included in the file
     9  // licenses/APL.txt.
    10  
    11  // "make test" would normally test this file, but it should only be tested
    12  // within docker compose. We also can't use just "gss" here because that
    13  // tag is reserved for the toplevel Makefile's linux-gnu build.
    14  
    15  // +build gss_compose
    16  
    17  package gss
    18  
    19  import (
    20  	gosql "database/sql"
    21  	"fmt"
    22  	"os/exec"
    23  	"regexp"
    24  	"strings"
    25  	"testing"
    26  
    27  	"github.com/cockroachdb/cockroach/pkg/util/timeutil"
    28  	"github.com/cockroachdb/errors"
    29  	"github.com/lib/pq"
    30  )
    31  
    32  func TestGSS(t *testing.T) {
    33  	connector, err := pq.NewConnector("user=root sslmode=require")
    34  	if err != nil {
    35  		t.Fatal(err)
    36  	}
    37  	db := gosql.OpenDB(connector)
    38  	defer db.Close()
    39  
    40  	tests := []struct {
    41  		// The hba.conf file/setting.
    42  		conf string
    43  		user string
    44  		// Error message of hba conf
    45  		hbaErr string
    46  		// Error message of gss login.
    47  		gssErr string
    48  	}{
    49  		{
    50  			conf:   `host all all all gss include_realm=0 nope=1`,
    51  			hbaErr: `unsupported option`,
    52  		},
    53  		{
    54  			conf:   `host all all all gss include_realm=1`,
    55  			hbaErr: `include_realm must be set to 0`,
    56  		},
    57  		{
    58  			conf:   `host all all all gss`,
    59  			hbaErr: `missing "include_realm=0"`,
    60  		},
    61  		{
    62  			conf:   `host all all all gss include_realm=0`,
    63  			user:   "tester",
    64  			gssErr: `GSS authentication requires an enterprise license`,
    65  		},
    66  		{
    67  			conf:   `host all tester all gss include_realm=0`,
    68  			user:   "tester",
    69  			gssErr: `GSS authentication requires an enterprise license`,
    70  		},
    71  		{
    72  			conf:   `host all nope all gss include_realm=0`,
    73  			user:   "tester",
    74  			gssErr: "no server.host_based_authentication.configuration entry",
    75  		},
    76  		{
    77  			conf:   `host all all all gss include_realm=0 krb_realm=MY.EX`,
    78  			user:   "tester",
    79  			gssErr: `GSS authentication requires an enterprise license`,
    80  		},
    81  		{
    82  			conf:   `host all all all gss include_realm=0 krb_realm=NOPE.EX`,
    83  			user:   "tester",
    84  			gssErr: `GSSAPI realm \(MY.EX\) didn't match any configured realm`,
    85  		},
    86  		{
    87  			conf:   `host all all all gss include_realm=0 krb_realm=NOPE.EX krb_realm=MY.EX`,
    88  			user:   "tester",
    89  			gssErr: `GSS authentication requires an enterprise license`,
    90  		},
    91  	}
    92  	for i, tc := range tests {
    93  		t.Run(fmt.Sprint(i), func(t *testing.T) {
    94  			if _, err := db.Exec(`SET CLUSTER SETTING server.host_based_authentication.configuration = $1`, tc.conf); !IsError(err, tc.hbaErr) {
    95  				t.Fatalf("expected err %v, got %v", tc.hbaErr, err)
    96  			}
    97  			if tc.hbaErr != "" {
    98  				return
    99  			}
   100  			if _, err := db.Exec(fmt.Sprintf(`CREATE USER IF NOT EXISTS '%s'`, tc.user)); err != nil {
   101  				t.Fatal(err)
   102  			}
   103  			out, err := exec.Command("psql", "-c", "SELECT 1", "-U", tc.user).CombinedOutput()
   104  			err = errors.Wrap(err, strings.TrimSpace(string(out)))
   105  			if !IsError(err, tc.gssErr) {
   106  				t.Errorf("expected err %v, got %v", tc.gssErr, err)
   107  			}
   108  		})
   109  	}
   110  }
   111  
   112  func TestGSSFileDescriptorCount(t *testing.T) {
   113  	// When the docker-compose.yml added a ulimit for the cockroach
   114  	// container the open file count would just stop there, it wouldn't
   115  	// cause cockroach to panic or error like I had hoped since it would
   116  	// allow a test to assert that multiple gss connections didn't leak
   117  	// file descriptors. Another possibility would be to have something
   118  	// track the open file count in the cockroach container, but that seems
   119  	// brittle and probably not worth the effort. However this test is
   120  	// useful when doing manual tracking of file descriptor count.
   121  	t.Skip("skip")
   122  
   123  	rootConnector, err := pq.NewConnector("user=root sslmode=require")
   124  	if err != nil {
   125  		t.Fatal(err)
   126  	}
   127  	rootDB := gosql.OpenDB(rootConnector)
   128  	defer rootDB.Close()
   129  
   130  	if _, err := rootDB.Exec(`SET CLUSTER SETTING server.host_based_authentication.configuration = $1`, "host all all all gss include_realm=0"); err != nil {
   131  		t.Fatal(err)
   132  	}
   133  	const user = "tester"
   134  	if _, err := rootDB.Exec(fmt.Sprintf(`CREATE USER IF NOT EXISTS '%s'`, user)); err != nil {
   135  		t.Fatal(err)
   136  	}
   137  
   138  	start := timeutil.Now()
   139  	for i := 0; i < 1000; i++ {
   140  		fmt.Println(i, timeutil.Since(start))
   141  		out, err := exec.Command("psql", "-c", "SELECT 1", "-U", user).CombinedOutput()
   142  		if IsError(err, "GSS authentication requires an enterprise license") {
   143  			t.Log(string(out))
   144  			t.Fatal(err)
   145  		}
   146  	}
   147  }
   148  
   149  func IsError(err error, re string) bool {
   150  	if err == nil && re == "" {
   151  		return true
   152  	}
   153  	if err == nil || re == "" {
   154  		return false
   155  	}
   156  	matched, merr := regexp.MatchString(re, err.Error())
   157  	if merr != nil {
   158  		return false
   159  	}
   160  	return matched
   161  }