adding USER command
This commit is contained in:
		
							parent
							
								
									976afd1992
								
							
						
					
					
						commit
						bc78e2b838
					
				|  | @ -0,0 +1,19 @@ | |||
| # Copyright 2018 Google, Inc. All rights reserved. | ||||
| # | ||||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| # you may not use this file except in compliance with the License. | ||||
| # You may obtain a copy of the License at | ||||
| # | ||||
| #     http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| # Unless required by applicable law or agreed to in writing, software | ||||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| # See the License for the specific language governing permissions and | ||||
| # limitations under the License. | ||||
| 
 | ||||
| FROM gcr.io/google-appengine/debian9 | ||||
| RUN useradd testuser | ||||
| RUN groupadd testgroup | ||||
| USER testuser:testgroup | ||||
| RUN echo "hey" > /etc/foo | ||||
|  | @ -0,0 +1,15 @@ | |||
| schemaVersion: '2.0.0' | ||||
| commandTests: | ||||
| - name: 'whoami' | ||||
|   command: 'whoami' | ||||
|   expectedOutput: ['testuser'] | ||||
|   excludedOutput: ['root'] | ||||
| - name: 'file owner' | ||||
|   command: 'ls' | ||||
|   args: ['-l', '/tmp/foo'] | ||||
|   expectedOutput: ['.*testuser.*', '.*testgroup.*'] | ||||
|   excludedOutput: ['.*root.*'] | ||||
| fileContentTests: | ||||
| - name: "/tmp/foo" | ||||
|   path: "/tmp/foo" | ||||
|   expectedContent: ["hey"] | ||||
|  | @ -80,6 +80,13 @@ var structureTests = []struct { | |||
| 		dockerBuildContext:    "/workspace/integration_tests/dockerfiles/", | ||||
| 		structureTestYamlPath: "/workspace/integration_tests/dockerfiles/test_metadata.yaml", | ||||
| 	}, | ||||
| 	{ | ||||
| 		description:           "test user command", | ||||
| 		dockerfilePath:        "/workspace/integration_tests/dockerfiles/Dockerfile_test_user_run", | ||||
| 		repo:                  "test-user", | ||||
| 		dockerBuildContext:    "/workspace/integration_tests/dockerfiles/", | ||||
| 		structureTestYamlPath: "/workspace/integration_tests/dockerfiles/test_user.yaml", | ||||
| 	}, | ||||
| } | ||||
| 
 | ||||
| type step struct { | ||||
|  |  | |||
|  | @ -30,6 +30,7 @@ type ExposeCommand struct { | |||
| } | ||||
| 
 | ||||
| func (r *ExposeCommand) ExecuteCommand(config *manifest.Schema2Config) error { | ||||
| 	logrus.Info("cmd: EXPOSE") | ||||
| 	// Grab the currently exposed ports
 | ||||
| 	existingPorts := config.ExposedPorts | ||||
| 	// Add any new ones in
 | ||||
|  |  | |||
|  | @ -29,6 +29,7 @@ type LabelCommand struct { | |||
| } | ||||
| 
 | ||||
| func (r *LabelCommand) ExecuteCommand(config *manifest.Schema2Config) error { | ||||
| 	logrus.Info("cmd: LABEL") | ||||
| 	return updateLabels(r.cmd.Labels, config) | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -22,7 +22,9 @@ import ( | |||
| 	"github.com/sirupsen/logrus" | ||||
| 	"os" | ||||
| 	"os/exec" | ||||
| 	"strconv" | ||||
| 	"strings" | ||||
| 	"syscall" | ||||
| ) | ||||
| 
 | ||||
| type RunCommand struct { | ||||
|  | @ -45,6 +47,26 @@ func (r *RunCommand) ExecuteCommand(config *manifest.Schema2Config) error { | |||
| 
 | ||||
| 	cmd := exec.Command(newCommand[0], newCommand[1:]...) | ||||
| 	cmd.Stdout = os.Stdout | ||||
| 	// If specified, run the command as a specific user
 | ||||
| 	if config.User != "" { | ||||
| 		userAndGroup := strings.Split(config.User, ":") | ||||
| 		// uid and gid need to be uint32
 | ||||
| 		uid64, err := strconv.ParseUint(userAndGroup[0], 10, 32) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 		uid := uint32(uid64) | ||||
| 		var gid uint32 | ||||
| 		if len(userAndGroup) > 1 { | ||||
| 			gid64, err := strconv.ParseUint(userAndGroup[1], 10, 32) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			gid = uint32(gid64) | ||||
| 		} | ||||
| 		cmd.SysProcAttr = &syscall.SysProcAttr{} | ||||
| 		cmd.SysProcAttr.Credential = &syscall.Credential{Uid: uid, Gid: gid} | ||||
| 	} | ||||
| 	return cmd.Run() | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -0,0 +1,79 @@ | |||
| /* | ||||
| Copyright 2018 Google LLC | ||||
| 
 | ||||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | ||||
| You may obtain a copy of the License at | ||||
| 
 | ||||
|     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
| 
 | ||||
| Unless required by applicable law or agreed to in writing, software | ||||
| distributed under the License is distributed on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| See the License for the specific language governing permissions and | ||||
| limitations under the License. | ||||
| */ | ||||
| 
 | ||||
| package commands | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/containers/image/manifest" | ||||
| 	"github.com/docker/docker/builder/dockerfile/instructions" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| 	"os/user" | ||||
| 	"strings" | ||||
| ) | ||||
| 
 | ||||
| type UserCommand struct { | ||||
| 	cmd *instructions.UserCommand | ||||
| } | ||||
| 
 | ||||
| func (r *UserCommand) ExecuteCommand(config *manifest.Schema2Config) error { | ||||
| 	logrus.Info("cmd: USER") | ||||
| 	u := r.cmd.User | ||||
| 	userAndGroup := strings.Split(u, ":") | ||||
| 	userStr := userAndGroup[0] | ||||
| 	var groupStr string | ||||
| 	if len(userAndGroup) > 1 { | ||||
| 		groupStr = userAndGroup[1] | ||||
| 	} | ||||
| 
 | ||||
| 	// Lookup by username
 | ||||
| 	userObj, err := user.Lookup(userStr) | ||||
| 	if err != nil { | ||||
| 		if _, ok := err.(user.UnknownUserError); ok { | ||||
| 			// Lookup by id
 | ||||
| 			userObj, err = user.LookupId(userStr) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 		} else { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// Same dance with groups
 | ||||
| 	var group *user.Group | ||||
| 	if groupStr != "" { | ||||
| 		group, err = user.LookupGroup(groupStr) | ||||
| 		if err != nil { | ||||
| 			if _, ok := err.(user.UnknownGroupError); ok { | ||||
| 				group, err = user.LookupGroupId(groupStr) | ||||
| 				if err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 			} else { | ||||
| 				return err | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	uid := userObj.Uid | ||||
| 	if group != nil { | ||||
| 		uid = uid + ":" + group.Gid | ||||
| 	} | ||||
| 
 | ||||
| 	logrus.Infof("Setting user to %s", uid) | ||||
| 	config.User = uid | ||||
| 	return nil | ||||
| } | ||||
|  | @ -0,0 +1,83 @@ | |||
| /* | ||||
| Copyright 2018 Google LLC | ||||
| 
 | ||||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| you may not use this file except in compliance with the License. | ||||
| You may obtain a copy of the License at | ||||
| 
 | ||||
|     http://www.apache.org/licenses/LICENSE-2.0
 | ||||
| 
 | ||||
| Unless required by applicable law or agreed to in writing, software | ||||
| distributed under the License is distributed on an "AS IS" BASIS, | ||||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| See the License for the specific language governing permissions and | ||||
| limitations under the License. | ||||
| */ | ||||
| package commands | ||||
| 
 | ||||
| import ( | ||||
| 	"github.com/GoogleCloudPlatform/k8s-container-builder/testutil" | ||||
| 	"github.com/containers/image/manifest" | ||||
| 	"github.com/docker/docker/builder/dockerfile/instructions" | ||||
| 	"testing" | ||||
| ) | ||||
| 
 | ||||
| var userTests = []struct { | ||||
| 	user        string | ||||
| 	expectedUid string | ||||
| 	shouldError bool | ||||
| }{ | ||||
| 	{ | ||||
| 		user:        "root", | ||||
| 		expectedUid: "0", | ||||
| 		shouldError: false, | ||||
| 	}, | ||||
| 	{ | ||||
| 		user:        "0", | ||||
| 		expectedUid: "0", | ||||
| 		shouldError: false, | ||||
| 	}, | ||||
| 	{ | ||||
| 		user:        "fakeUser", | ||||
| 		expectedUid: "", | ||||
| 		shouldError: true, | ||||
| 	}, | ||||
| 	{ | ||||
| 		user:        "root:root", | ||||
| 		expectedUid: "0:0", | ||||
| 		shouldError: false, | ||||
| 	}, | ||||
| 	{ | ||||
| 		user:        "0:root", | ||||
| 		expectedUid: "0:0", | ||||
| 		shouldError: false, | ||||
| 	}, | ||||
| 	{ | ||||
| 		user:        "root:0", | ||||
| 		expectedUid: "0:0", | ||||
| 		shouldError: false, | ||||
| 	}, | ||||
| 	{ | ||||
| 		user:        "0:0", | ||||
| 		expectedUid: "0:0", | ||||
| 		shouldError: false, | ||||
| 	}, | ||||
| 	{ | ||||
| 		user:        "root:fakeGroup", | ||||
| 		expectedUid: "", | ||||
| 		shouldError: true, | ||||
| 	}, | ||||
| } | ||||
| 
 | ||||
| func TestUpdateUser(t *testing.T) { | ||||
| 	for _, test := range userTests { | ||||
| 		cfg := &manifest.Schema2Config{} | ||||
| 		cmd := UserCommand{ | ||||
| 			&instructions.UserCommand{ | ||||
| 				User: test.user, | ||||
| 			}, | ||||
| 		} | ||||
| 		err := cmd.ExecuteCommand(cfg) | ||||
| 		testutil.CheckErrorAndDeepEqual(t, test.shouldError, err, test.expectedUid, cfg.User) | ||||
| 	} | ||||
| } | ||||
		Loading…
	
		Reference in New Issue