package docker import ( "os" "testing" "github.com/openshift/source-to-image/pkg/api" "github.com/openshift/source-to-image/pkg/api/constants" "github.com/openshift/source-to-image/pkg/util/user" ) func rangeList(str string) *user.RangeList { l, err := user.ParseRangeList(str) if err != nil { panic(err) } return l } func TestCheckAllowedUser(t *testing.T) { tests := []struct { name string allowedUIDs *user.RangeList user string onbuild []string expectErr bool assembleUser string labels map[string]string }{ { name: "AllowedUIDs is not set", allowedUIDs: rangeList(""), user: "root", onbuild: []string{}, expectErr: false, }, { name: "AllowedUIDs is set, non-numeric user", allowedUIDs: rangeList("0"), user: "default", onbuild: []string{}, expectErr: true, }, { name: "AllowedUIDs is set, user 0", allowedUIDs: rangeList("1-"), user: "0", onbuild: []string{}, expectErr: true, }, { name: "AllowedUIDs is set, numeric user, non-numeric onbuild", allowedUIDs: rangeList("1-10,30-"), user: "100", onbuild: []string{"COPY test test", "USER default"}, expectErr: true, }, { name: "AllowedUIDs is set, numeric user, no onbuild user directive", allowedUIDs: rangeList("1-10,30-"), user: "200", onbuild: []string{"VOLUME /data"}, expectErr: false, }, { name: "AllowedUIDs is set, numeric user, onbuild numeric user directive", allowedUIDs: rangeList("200,500-"), user: "200", onbuild: []string{"USER 500", "VOLUME /data"}, expectErr: false, }, { name: "AllowedUIDs is set, numeric user, onbuild user 0", allowedUIDs: rangeList("1-"), user: "200", onbuild: []string{"RUN echo \"hello world\"", "USER 0"}, expectErr: true, }, { name: "AllowedUIDs is set, numeric user, onbuild numeric user directive, upper bound range", allowedUIDs: rangeList("-1000"), user: "80", onbuild: []string{"USER 501", "VOLUME /data"}, expectErr: false, }, { name: "AllowedUIDs is set, numeric user with group", allowedUIDs: rangeList("1-"), user: "5:5000", expectErr: false, }, { name: "AllowedUIDs is set, numeric user with named group", allowedUIDs: rangeList("1-"), user: "5:group", expectErr: false, }, { name: "AllowedUIDs is set, named user with group", allowedUIDs: rangeList("1-"), user: "root:wheel", expectErr: true, }, { name: "AllowedUIDs is set, numeric user, onbuild user with group", allowedUIDs: rangeList("1-"), user: "200", onbuild: []string{"RUN echo \"hello world\"", "USER 10:100"}, expectErr: false, }, { name: "AllowedUIDs is set, numeric user, onbuild named user with group", allowedUIDs: rangeList("1-"), user: "200", onbuild: []string{"RUN echo \"hello world\"", "USER root:wheel"}, expectErr: true, }, { name: "AllowedUIDs is set, numeric user, onbuild user with named group", allowedUIDs: rangeList("1-"), user: "200", onbuild: []string{"RUN echo \"hello world\"", "USER 10:wheel"}, expectErr: false, }, { name: "AllowedUIDs is set, numeric user, assemble user override ok", allowedUIDs: rangeList("1-"), user: "200", assembleUser: "10", expectErr: false, }, { name: "AllowedUIDs is set, numeric user, root assemble user", allowedUIDs: rangeList("1-"), user: "200", assembleUser: "0", expectErr: true, }, { name: "AllowedUIDs is set, numeric user, assemble user label ok", allowedUIDs: rangeList("1-"), user: "200", labels: map[string]string{constants.AssembleUserLabel: "10"}, expectErr: false, }, { name: "AllowedUIDs is set, numeric user, assemble user label root", allowedUIDs: rangeList("1-"), user: "200", labels: map[string]string{constants.AssembleUserLabel: "0"}, expectErr: true, }, { name: "AllowedUIDs is set, root image user, assemble user label ok", allowedUIDs: rangeList("1-"), user: "0", labels: map[string]string{constants.AssembleUserLabel: "10"}, expectErr: false, }, { name: "AllowedUIDs is set, root image user, assemble user override ok", allowedUIDs: rangeList("1-"), user: "0", assembleUser: "10", expectErr: false, }, { name: "AllowedUIDs is set, root image user, onbuild root named user with group, assemble user label ok", allowedUIDs: rangeList("1-"), user: "0", labels: map[string]string{constants.AssembleUserLabel: "10"}, onbuild: []string{"RUN echo \"hello world\"", "USER root:wheel", "RUN echo \"i am gROOT\"", "USER 10"}, expectErr: true, }, { name: "AllowedUIDs is set, root image user, onbuild root named user with group, assemble user override ok", allowedUIDs: rangeList("1-"), user: "0", assembleUser: "10", onbuild: []string{"RUN echo \"hello world\"", "USER root:wheel", "RUN echo \"i am gROOT\"", "USER 10"}, expectErr: true, }, } for _, tc := range tests { docker := &FakeDocker{ GetImageUserResult: tc.user, OnBuildResult: tc.onbuild, Labels: tc.labels, } err := CheckAllowedUser(docker, "", *tc.allowedUIDs, len(tc.onbuild) > 0, tc.assembleUser) if err != nil && !tc.expectErr { t.Errorf("%s: unexpected error: %v", tc.name, err) } if err == nil && tc.expectErr { t.Errorf("%s: expected error, but did not get any", tc.name) } } } func TestGetDefaultDockerConfig(t *testing.T) { tests := []struct { envHost string envCertPath string envTLSVerify string envTLS string expectedHost string expectedCertFile string expectedTLSVerify bool expectedTLS bool }{ { envHost: "tcp://docker:2376", envCertPath: "/expected/cert/path", envTLSVerify: "true", envTLS: "true", expectedHost: "tcp://docker:2376", expectedCertFile: "/expected/cert/path/cert.pem", expectedTLSVerify: true, expectedTLS: true, }, { envHost: "", envCertPath: "", envTLSVerify: "", envTLS: "", expectedHost: "unix:///var/run/docker.sock", expectedCertFile: Dir() + "/cert.pem", expectedTLSVerify: false, expectedTLS: false, }, } for _, tc := range tests { oldHost := os.Getenv("DOCKER_HOST") oldCertPath := os.Getenv("DOCKER_CERT_PATH") oldTLSVerify := os.Getenv("DOCKER_TLS_VERIFY") oldTLS := os.Getenv("DOCKER_TLS") os.Setenv("DOCKER_HOST", tc.envHost) os.Setenv("DOCKER_CERT_PATH", tc.envCertPath) os.Setenv("DOCKER_TLS_VERIFY", tc.envTLSVerify) os.Setenv("DOCKER_TLS", tc.envTLS) defer os.Setenv("DOCKER_HOST", oldHost) defer os.Setenv("DOCKER_CERT_PATH", oldCertPath) defer os.Setenv("DOCKER_TLS_VERIFY", oldTLSVerify) defer os.Setenv("DOCKER_TLS", oldTLS) cfg := GetDefaultDockerConfig() if tc.expectedHost != cfg.Endpoint { t.Errorf("Endpoint: expected '%s', but got '%s'", tc.expectedHost, cfg.Endpoint) } if tc.expectedCertFile != cfg.CertFile { t.Errorf("CertFile: expected '%s', but got '%s'", tc.expectedCertFile, cfg.CertFile) } if tc.expectedTLSVerify != cfg.TLSVerify { t.Errorf("TLSVerify: expected '%t', but got '%t'", tc.expectedTLSVerify, cfg.TLSVerify) } if tc.expectedTLS != cfg.UseTLS { t.Errorf("UseTLS: expected '%t', but got '%t'", tc.expectedTLS, cfg.UseTLS) } } } func TestGetAssembleUser(t *testing.T) { testCases := []struct { name string containerUser string assembleUserLabel string expectedResult string extractedResult string }{ { name: "empty", }, { name: "container user set", containerUser: "1002", expectedResult: "1002", extractedResult: "1002", }, { name: "container user:group set", containerUser: "1002:1002", expectedResult: "1002:1002", extractedResult: "1002", }, { name: "assemble user label set", assembleUserLabel: "1003", expectedResult: "1003", extractedResult: "1003", }, { name: "assemble user:group label set", assembleUserLabel: "1003:1003", expectedResult: "1003:1003", extractedResult: "1003", }, { name: "assemble user override", containerUser: "1002", assembleUserLabel: "1003", expectedResult: "1003", extractedResult: "1003", }, { name: "assemble user:group override", containerUser: "1002:1002", assembleUserLabel: "1003:1003", expectedResult: "1003:1003", extractedResult: "1003", }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { fakeDocker := &FakeDocker{ GetImageUserResult: tc.containerUser, AssembleRuntimeUserResult: tc.assembleUserLabel, Labels: make(map[string]string), } if tc.assembleUserLabel != "" { fakeDocker.Labels[constants.AssembleUserLabel] = tc.assembleUserLabel } assembleUser, err := GetAssembleUser(fakeDocker, &api.Config{BuilderImage: "dummy-image:latest"}) if err != nil { t.Fatalf("unexpected error: %v", err) } if assembleUser != tc.expectedResult { t.Fatalf("expected assemble user %s, got %s", tc.expectedResult, assembleUser) } extractedUser := extractUser(assembleUser) if extractedUser != tc.extractedResult { t.Fatalf("expected extracted user %s, got %s", tc.extractedResult, extractedUser) } }) } }