cuelabs.dev/go/oci/ociregistry@v0.0.0-20240906074133-82eb438dd565/ocifilter/select_test.go (about)

     1  // Copyright 2024 CUE Labs AG
     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  package ocifilter
    16  
    17  import (
    18  	"context"
    19  	"errors"
    20  	"strings"
    21  	"testing"
    22  
    23  	"github.com/go-quicktest/qt"
    24  	"github.com/opencontainers/go-digest"
    25  
    26  	"cuelabs.dev/go/oci/ociregistry"
    27  	"cuelabs.dev/go/oci/ociregistry/ocimem"
    28  )
    29  
    30  func TestAccessCheckerErrorReturn(t *testing.T) {
    31  	ctx := context.Background()
    32  	testErr := errors.New("some error")
    33  	r1 := AccessChecker(ocimem.New(), func(repoName string, access AccessKind) error {
    34  		qt.Check(t, qt.Equals(repoName, "foo/bar"))
    35  		qt.Check(t, qt.Equals(access, AccessRead))
    36  		return testErr
    37  	})
    38  	_, err := r1.GetTag(ctx, "foo/bar", "t1")
    39  	qt.Assert(t, qt.ErrorIs(err, testErr))
    40  }
    41  
    42  func TestAccessCheckerAccessRequest(t *testing.T) {
    43  	assertAccess := func(wantAccess []accessCheck, do func(ctx context.Context, r ociregistry.Interface) error) {
    44  		testErr := errors.New("some error")
    45  		var gotAccess []accessCheck
    46  		r := AccessChecker(&ociregistry.Funcs{
    47  			NewError: func(ctx context.Context, methodName, repo string) error {
    48  				return testErr
    49  			},
    50  		}, func(repoName string, access AccessKind) error {
    51  			gotAccess = append(gotAccess, accessCheck{repoName, access})
    52  			return nil
    53  		})
    54  		err := do(context.Background(), r)
    55  		qt.Check(t, qt.ErrorIs(err, testErr))
    56  		qt.Check(t, qt.DeepEquals(gotAccess, wantAccess))
    57  	}
    58  	assertAccess([]accessCheck{
    59  		{"foo/read", AccessRead},
    60  	}, func(ctx context.Context, r ociregistry.Interface) error {
    61  		_, err := r.GetBlob(ctx, "foo/read", "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
    62  		return err
    63  	})
    64  	assertAccess([]accessCheck{
    65  		{"foo/read", AccessRead},
    66  	}, func(ctx context.Context, r ociregistry.Interface) error {
    67  		rd, err := r.GetBlobRange(ctx, "foo/read", "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 100, 200)
    68  		if rd != nil {
    69  			rd.Close()
    70  		}
    71  		return err
    72  	})
    73  
    74  	assertAccess([]accessCheck{
    75  		{"foo/read", AccessRead},
    76  	}, func(ctx context.Context, r ociregistry.Interface) error {
    77  		rd, err := r.GetManifest(ctx, "foo/read", "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
    78  		if rd != nil {
    79  			rd.Close()
    80  		}
    81  		return err
    82  	})
    83  
    84  	assertAccess([]accessCheck{
    85  		{"foo/read", AccessRead},
    86  	}, func(ctx context.Context, r ociregistry.Interface) error {
    87  		rd, err := r.GetTag(ctx, "foo/read", "sometag")
    88  		if rd != nil {
    89  			rd.Close()
    90  		}
    91  		return err
    92  	})
    93  
    94  	assertAccess([]accessCheck{
    95  		{"foo/read", AccessRead},
    96  	}, func(ctx context.Context, r ociregistry.Interface) error {
    97  		_, err := r.ResolveBlob(ctx, "foo/read", "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
    98  		return err
    99  	})
   100  
   101  	assertAccess([]accessCheck{
   102  		{"foo/read", AccessRead},
   103  	}, func(ctx context.Context, r ociregistry.Interface) error {
   104  		_, err := r.ResolveManifest(ctx, "foo/read", "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
   105  		return err
   106  	})
   107  
   108  	assertAccess([]accessCheck{
   109  		{"foo/read", AccessRead},
   110  	}, func(ctx context.Context, r ociregistry.Interface) error {
   111  		_, err := r.ResolveTag(ctx, "foo/read", "sometag")
   112  		return err
   113  	})
   114  
   115  	assertAccess([]accessCheck{
   116  		{"foo/write", AccessWrite},
   117  	}, func(ctx context.Context, r ociregistry.Interface) error {
   118  		_, err := r.PushBlob(ctx, "foo/write", ociregistry.Descriptor{
   119  			MediaType: "application/json",
   120  			Digest:    "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
   121  			Size:      3,
   122  		}, strings.NewReader("foo"))
   123  		return err
   124  	})
   125  
   126  	assertAccess([]accessCheck{
   127  		{"foo/write", AccessWrite},
   128  	}, func(ctx context.Context, r ociregistry.Interface) error {
   129  		w, err := r.PushBlobChunked(ctx, "foo/write", 0)
   130  		if err != nil {
   131  			return err
   132  		}
   133  		w.Close()
   134  		return nil
   135  	})
   136  
   137  	assertAccess([]accessCheck{
   138  		{"foo/write", AccessWrite},
   139  	}, func(ctx context.Context, r ociregistry.Interface) error {
   140  		w, err := r.PushBlobChunkedResume(ctx, "foo/write", "/someid", 3, 0)
   141  		if err != nil {
   142  			return err
   143  		}
   144  		data := []byte("some data")
   145  		if _, err := w.Write(data); err != nil {
   146  			return err
   147  		}
   148  		_, err = w.Commit(digest.FromBytes(data))
   149  		return err
   150  	})
   151  
   152  	assertAccess([]accessCheck{
   153  		{"foo/read", AccessRead},
   154  		{"foo/write", AccessWrite},
   155  	}, func(ctx context.Context, r ociregistry.Interface) error {
   156  		_, err := r.MountBlob(ctx, "foo/read", "foo/write", "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
   157  		return err
   158  	})
   159  
   160  	assertAccess([]accessCheck{
   161  		{"foo/write", AccessWrite},
   162  	}, func(ctx context.Context, r ociregistry.Interface) error {
   163  		_, err := r.PushManifest(ctx, "foo/write", "sometag", []byte("something"), "application/json")
   164  		return err
   165  	})
   166  
   167  	assertAccess([]accessCheck{
   168  		{"foo/write", AccessDelete},
   169  	}, func(ctx context.Context, r ociregistry.Interface) error {
   170  		return r.DeleteBlob(ctx, "foo/write", "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
   171  	})
   172  
   173  	assertAccess([]accessCheck{
   174  		{"foo/write", AccessDelete},
   175  	}, func(ctx context.Context, r ociregistry.Interface) error {
   176  		return r.DeleteManifest(ctx, "foo/write", "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff")
   177  	})
   178  
   179  	assertAccess([]accessCheck{
   180  		{"foo/write", AccessDelete},
   181  	}, func(ctx context.Context, r ociregistry.Interface) error {
   182  		return r.DeleteTag(ctx, "foo/write", "sometag")
   183  	})
   184  
   185  	assertAccess([]accessCheck{
   186  		{"*", AccessList},
   187  	}, func(ctx context.Context, r ociregistry.Interface) error {
   188  		_, err := ociregistry.All(r.Repositories(ctx, ""))
   189  		return err
   190  	})
   191  
   192  	assertAccess([]accessCheck{
   193  		{"foo/read", AccessList},
   194  	}, func(ctx context.Context, r ociregistry.Interface) error {
   195  		_, err := ociregistry.All(r.Tags(ctx, "foo/read", ""))
   196  		return err
   197  	})
   198  
   199  	assertAccess([]accessCheck{
   200  		{"foo/read", AccessList},
   201  	}, func(ctx context.Context, r ociregistry.Interface) error {
   202  		_, err := ociregistry.All(r.Referrers(ctx, "foo/read", "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", ""))
   203  		return err
   204  	})
   205  }
   206  
   207  type accessCheck struct {
   208  	Repo  string
   209  	Check AccessKind
   210  }