github.com/rkt/rkt@v1.30.1-0.20200224141603-171c416fac02/tests/rkt_auth_test.go (about)

     1  // Copyright 2015 The rkt Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // +build host coreos src kvm
    16  
    17  package main
    18  
    19  import (
    20  	"fmt"
    21  	"os"
    22  	"path/filepath"
    23  	"strings"
    24  	"testing"
    25  
    26  	"github.com/rkt/rkt/tests/testutils"
    27  	taas "github.com/rkt/rkt/tests/testutils/aci-server"
    28  )
    29  
    30  func TestAuthSanity(t *testing.T) {
    31  	ctx := testutils.NewRktRunCtx()
    32  	defer ctx.Cleanup()
    33  	server, image := runAuthServer(t, taas.AuthNone)
    34  	defer authCleanup(server, image)
    35  	expectedRunRkt(ctx, t, server.URL, "sanity", authSuccessfulDownload)
    36  }
    37  
    38  const (
    39  	// It cannot have any spaces, because of an actool limitation
    40  	// - if we pass an `--exec=/inspect
    41  	// --print-msg='Authentication succeeded.'` string to actool
    42  	// it will split the --exec value by spaces, disregarding the
    43  	// single quotes around "Authentication succeeded.". The
    44  	// result is that /inspect receives two parameters -
    45  	// "--print-msg='Authentication" and "succeeded.'"
    46  	authSuccessfulDownload = "AuthenticationSucceeded."
    47  	authFailedDownload     = "bad HTTP status code: 401"
    48  	authACIName            = "rkt-inspect-auth-test.aci"
    49  )
    50  
    51  type authConfDir int
    52  
    53  const (
    54  	authConfDirNone authConfDir = iota
    55  	authConfDirLocal
    56  	authConfDirSystem
    57  )
    58  
    59  type genericAuthTest struct {
    60  	name         string
    61  	confDir      authConfDir
    62  	expectedLine string
    63  }
    64  
    65  func TestAuthBasic(t *testing.T) {
    66  	tests := []genericAuthTest{
    67  		{"basic-no-config", authConfDirNone, authFailedDownload},
    68  		{"basic-local-config", authConfDirLocal, authSuccessfulDownload},
    69  		{"basic-system-config", authConfDirSystem, authSuccessfulDownload},
    70  	}
    71  	testAuthGeneric(t, taas.AuthBasic, tests)
    72  }
    73  
    74  func TestAuthOauth(t *testing.T) {
    75  	tests := []genericAuthTest{
    76  		{"oauth-no-config", authConfDirNone, authFailedDownload},
    77  		{"oauth-local-config", authConfDirLocal, authSuccessfulDownload},
    78  		{"oauth-system-config", authConfDirSystem, authSuccessfulDownload},
    79  	}
    80  	testAuthGeneric(t, taas.AuthOauth, tests)
    81  }
    82  
    83  func testAuthGeneric(t *testing.T, auth taas.AuthType, tests []genericAuthTest) {
    84  	server, image := runAuthServer(t, auth)
    85  	defer authCleanup(server, image)
    86  	ctx := testutils.NewRktRunCtx()
    87  	defer ctx.Cleanup()
    88  	for _, tt := range tests {
    89  		switch tt.confDir {
    90  		case authConfDirNone:
    91  			// no config to write
    92  		case authConfDirLocal:
    93  			writeConfig(t, authDir(ctx.LocalDir()), "test.json", server.Conf)
    94  		case authConfDirSystem:
    95  			writeConfig(t, authDir(ctx.SystemDir()), "test.json", server.Conf)
    96  		default:
    97  			panic("Wrong config directory")
    98  		}
    99  		expectedRunRkt(ctx, t, server.URL, tt.name, tt.expectedLine)
   100  		ctx.Reset()
   101  	}
   102  }
   103  
   104  func TestAuthOverride(t *testing.T) {
   105  	ctx := testutils.NewRktRunCtx()
   106  	defer ctx.Cleanup()
   107  	server, image := runAuthServer(t, taas.AuthOauth)
   108  	defer authCleanup(server, image)
   109  	hash := "sha512-" + getHashOrPanic(image)
   110  	tests := []struct {
   111  		systemConfig         string
   112  		localConfig          string
   113  		name                 string
   114  		resultBeforeOverride string
   115  		resultAfterOverride  string
   116  	}{
   117  		{server.Conf, getInvalidOAuthConfig(server.Conf), "valid-system-invalid-local", authSuccessfulDownload, authFailedDownload},
   118  		{getInvalidOAuthConfig(server.Conf), server.Conf, "invalid-system-valid-local", authFailedDownload, authSuccessfulDownload},
   119  	}
   120  	for _, tt := range tests {
   121  		writeConfig(t, authDir(ctx.SystemDir()), "test.json", tt.systemConfig)
   122  		expectedRunRkt(ctx, t, server.URL, tt.name+"-1", tt.resultBeforeOverride)
   123  		if tt.resultBeforeOverride == authSuccessfulDownload {
   124  			// Remove the image from the store since it was fetched in the
   125  			// previous run and the test aci-server returns a
   126  			// Cache-Control max-age header
   127  			removeFromCas(t, ctx, hash)
   128  		}
   129  		writeConfig(t, authDir(ctx.LocalDir()), "test.json", tt.localConfig)
   130  		expectedRunRkt(ctx, t, server.URL, tt.name+"-2", tt.resultAfterOverride)
   131  		ctx.Reset()
   132  	}
   133  }
   134  
   135  func TestAuthIgnore(t *testing.T) {
   136  	server, image := runAuthServer(t, taas.AuthOauth)
   137  	defer authCleanup(server, image)
   138  	testAuthIgnoreBogusFiles(t, server)
   139  	testAuthIgnoreSubdirectories(t, server)
   140  }
   141  
   142  func testAuthIgnoreBogusFiles(t *testing.T, server *taas.Server) {
   143  	ctx := testutils.NewRktRunCtx()
   144  	defer ctx.Cleanup()
   145  	writeConfig(t, authDir(ctx.SystemDir()), "README", "This is system config")
   146  	writeConfig(t, authDir(ctx.LocalDir()), "README", "This is local config")
   147  	writeConfig(t, authDir(ctx.SystemDir()), "test.notjson", server.Conf)
   148  	writeConfig(t, authDir(ctx.LocalDir()), "test.notjson", server.Conf)
   149  	expectedRunRkt(ctx, t, server.URL, "oauth-bogus-files", authFailedDownload)
   150  }
   151  
   152  func testAuthIgnoreSubdirectories(t *testing.T, server *taas.Server) {
   153  	ctx := testutils.NewRktRunCtx()
   154  	defer ctx.Cleanup()
   155  	localSubdir := filepath.Join(ctx.LocalDir(), "subdir")
   156  	systemSubdir := filepath.Join(ctx.SystemDir(), "subdir")
   157  	writeConfig(t, authDir(localSubdir), "test.json", server.Conf)
   158  	writeConfig(t, authDir(systemSubdir), "test.json", server.Conf)
   159  	expectedRunRkt(ctx, t, server.URL, "oauth-subdirectories", authFailedDownload)
   160  }
   161  
   162  func runAuthServer(t *testing.T, auth taas.AuthType) (*taas.Server, string) {
   163  	setup := taas.GetDefaultServerSetup()
   164  	setup.Auth = auth
   165  	setup.Port = taas.PortRandom
   166  	server := runServer(t, setup)
   167  	image := patchTestACI(authACIName, fmt.Sprintf("--exec=/inspect --print-msg='%s'", authSuccessfulDownload))
   168  	fileSet := make(map[string]string, 1)
   169  	fileSet[authACIName] = image
   170  	if err := server.UpdateFileSet(fileSet); err != nil {
   171  		t.Fatalf("Failed to populate a file list in test aci server: %v", err)
   172  	}
   173  	return server, image
   174  }
   175  
   176  func authCleanup(server *taas.Server, image string) {
   177  	server.Close()
   178  	_ = os.Remove(image)
   179  }
   180  
   181  // expectedRunRkt tries to fetch and run an auth test ACI from host.
   182  func expectedRunRkt(ctx *testutils.RktRunCtx, t *testing.T, host, testName, line string) {
   183  	t.Logf("test name: %s", testName)
   184  	// First, check that --insecure-options=image,tls is required
   185  	// The server does not provide signatures for now.
   186  	cmd := fmt.Sprintf(`%s --debug run --no-store --mds-register=false %s/%s`, ctx.Cmd(), host, authACIName)
   187  	child := spawnOrFail(t, cmd)
   188  	defer child.Wait()
   189  	signatureErrorLine := "error downloading the signature file"
   190  	if err := expectWithOutput(child, signatureErrorLine); err != nil {
   191  		t.Fatalf("Didn't receive expected output %q: %v", signatureErrorLine, err)
   192  	}
   193  
   194  	// Then, run with --insecure-options=image,tls
   195  	cmd = fmt.Sprintf(`%s --debug --insecure-options=image,tls run --no-store --mds-register=false %s/%s`, ctx.Cmd(), host, authACIName)
   196  	child = spawnOrFail(t, cmd)
   197  	defer child.Wait()
   198  	if err := expectWithOutput(child, line); err != nil {
   199  		t.Fatalf("Didn't receive expected output %q: %v", line, err)
   200  	}
   201  }
   202  
   203  func getInvalidOAuthConfig(conf string) string {
   204  	return strings.Replace(conf, "sometoken", "someobviouslywrongtoken", 1)
   205  }