Add WithAmbientCapabilities opt
Closes #2516 This can be used for non-root users binding to low ports. Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
parent
0a3f87ec2e
commit
4b9b3e8fc9
@ -1356,3 +1356,120 @@ func TestUIDNoGID(t *testing.T) {
|
|||||||
t.Fatalf("expected gid 0 but received %d", gid)
|
t.Fatalf("expected gid 0 but received %d", gid)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBindLowPortNonRoot(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
client, err := newClient(t, address)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
var (
|
||||||
|
image Image
|
||||||
|
ctx, cancel = testContext()
|
||||||
|
id = t.Name()
|
||||||
|
)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
image, err = client.GetImage(ctx, testImage)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
container, err := client.NewContainer(ctx, id,
|
||||||
|
WithNewSnapshot(id, image),
|
||||||
|
WithNewSpec(oci.WithImageConfig(image), withProcessArgs("nc", "-l", "-p", "80"), oci.WithUIDGID(1000, 1000)),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer container.Delete(ctx, WithSnapshotCleanup)
|
||||||
|
|
||||||
|
task, err := container.NewTask(ctx, empty())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer task.Delete(ctx)
|
||||||
|
|
||||||
|
statusC, err := task.Wait(ctx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := task.Start(ctx); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
status := <-statusC
|
||||||
|
code, _, err := status.Result()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if code != 1 {
|
||||||
|
t.Errorf("expected status 1 from wait but received %d", code)
|
||||||
|
}
|
||||||
|
if _, err := task.Delete(ctx); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBindLowPortNonOpt(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
client, err := newClient(t, address)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
var (
|
||||||
|
image Image
|
||||||
|
ctx, cancel = testContext()
|
||||||
|
id = t.Name()
|
||||||
|
)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
image, err = client.GetImage(ctx, testImage)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
container, err := client.NewContainer(ctx, id,
|
||||||
|
WithNewSnapshot(id, image),
|
||||||
|
WithNewSpec(oci.WithImageConfig(image), withProcessArgs("nc", "-l", "-p", "80"), oci.WithUIDGID(1000, 1000), oci.WithAmbientCapabilities([]string{"CAP_NET_BIND_SERVICE"})),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer container.Delete(ctx, WithSnapshotCleanup)
|
||||||
|
|
||||||
|
task, err := container.NewTask(ctx, empty())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer task.Delete(ctx)
|
||||||
|
|
||||||
|
statusC, err := task.Wait(ctx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := task.Start(ctx); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
task.Kill(ctx, unix.SIGTERM)
|
||||||
|
}()
|
||||||
|
status := <-statusC
|
||||||
|
code, _, err := status.Result()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
// 128 + sigterm
|
||||||
|
if code != 143 {
|
||||||
|
t.Errorf("expected status 143 from wait but received %d", code)
|
||||||
|
}
|
||||||
|
if _, err := task.Delete(ctx); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -486,6 +486,18 @@ func getAllCapabilities() []string {
|
|||||||
return caps
|
return caps
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithAmbientCapabilities set the Linux ambient capabilities for the process
|
||||||
|
// Ambient capabilities should only be set for non-root users or the caller should
|
||||||
|
// understand how these capabilities are used and set
|
||||||
|
func WithAmbientCapabilities(caps []string) SpecOpts {
|
||||||
|
return func(_ context.Context, _ Client, _ *containers.Container, s *Spec) error {
|
||||||
|
setCapabilities(s)
|
||||||
|
|
||||||
|
s.Process.Capabilities.Ambient = caps
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var errNoUsersFound = errors.New("no users found")
|
var errNoUsersFound = errors.New("no users found")
|
||||||
|
|
||||||
func getUIDGIDFromPath(root string, filter func(user.User) bool) (uid, gid uint32, err error) {
|
func getUIDGIDFromPath(root string, filter func(user.User) bool) (uid, gid uint32, err error) {
|
||||||
|
Loading…
Reference in New Issue
Block a user