...

Source file src/cuelabs.dev/go/oci/ociregistry/ocifilter/select.go

Documentation: cuelabs.dev/go/oci/ociregistry/ocifilter

     1  // Copyright 2023 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  	"io"
    20  
    21  	"cuelabs.dev/go/oci/ociregistry"
    22  )
    23  
    24  // Select returns a wrapper for r that provides only
    25  // repositories for which allow returns true.
    26  //
    27  // Requests for disallowed repositories will return ErrNameUnknown
    28  // errors on read and ErrDenied on write.
    29  func Select(r ociregistry.Interface, allow func(repoName string) bool) ociregistry.Interface {
    30  	return &selectRegistry{
    31  		allow: allow,
    32  		r:     r,
    33  	}
    34  }
    35  
    36  type selectRegistry struct {
    37  	// Embed Funcs rather than the interface directly so that
    38  	// if new methods are added and selectRegistry isn't updated,
    39  	// we fall back to returning an error rather than passing through the method.
    40  	*ociregistry.Funcs
    41  	allow func(repoName string) bool
    42  	r     ociregistry.Interface
    43  }
    44  
    45  func (r *selectRegistry) GetBlob(ctx context.Context, repo string, digest ociregistry.Digest) (ociregistry.BlobReader, error) {
    46  	if !r.allow(repo) {
    47  		return nil, ociregistry.ErrNameUnknown
    48  	}
    49  	return r.r.GetBlob(ctx, repo, digest)
    50  }
    51  
    52  func (r *selectRegistry) GetBlobRange(ctx context.Context, repo string, digest ociregistry.Digest, offset0, offset1 int64) (ociregistry.BlobReader, error) {
    53  	if !r.allow(repo) {
    54  		return nil, ociregistry.ErrNameUnknown
    55  	}
    56  	return r.r.GetBlobRange(ctx, repo, digest, offset0, offset1)
    57  }
    58  
    59  func (r *selectRegistry) GetManifest(ctx context.Context, repo string, digest ociregistry.Digest) (ociregistry.BlobReader, error) {
    60  	if !r.allow(repo) {
    61  		return nil, ociregistry.ErrNameUnknown
    62  	}
    63  	return r.r.GetManifest(ctx, repo, digest)
    64  }
    65  
    66  func (r *selectRegistry) GetTag(ctx context.Context, repo string, tagName string) (ociregistry.BlobReader, error) {
    67  	if !r.allow(repo) {
    68  		return nil, ociregistry.ErrNameUnknown
    69  	}
    70  	return r.r.GetTag(ctx, repo, tagName)
    71  }
    72  
    73  func (r *selectRegistry) ResolveBlob(ctx context.Context, repo string, digest ociregistry.Digest) (ociregistry.Descriptor, error) {
    74  	if !r.allow(repo) {
    75  		return ociregistry.Descriptor{}, ociregistry.ErrNameUnknown
    76  	}
    77  	return r.r.ResolveBlob(ctx, repo, digest)
    78  }
    79  
    80  func (r *selectRegistry) ResolveManifest(ctx context.Context, repo string, digest ociregistry.Digest) (ociregistry.Descriptor, error) {
    81  	if !r.allow(repo) {
    82  		return ociregistry.Descriptor{}, ociregistry.ErrNameUnknown
    83  	}
    84  	return r.r.ResolveManifest(ctx, repo, digest)
    85  }
    86  
    87  func (r *selectRegistry) ResolveTag(ctx context.Context, repo string, tagName string) (ociregistry.Descriptor, error) {
    88  	if !r.allow(repo) {
    89  		return ociregistry.Descriptor{}, ociregistry.ErrNameUnknown
    90  	}
    91  	return r.r.ResolveTag(ctx, repo, tagName)
    92  }
    93  
    94  func (r *selectRegistry) PushBlob(ctx context.Context, repo string, desc ociregistry.Descriptor, rd io.Reader) (ociregistry.Descriptor, error) {
    95  	if !r.allow(repo) {
    96  		return ociregistry.Descriptor{}, ociregistry.ErrDenied
    97  	}
    98  	return r.r.PushBlob(ctx, repo, desc, rd)
    99  }
   100  
   101  func (r *selectRegistry) PushBlobChunked(ctx context.Context, repo string, chunkSize int) (ociregistry.BlobWriter, error) {
   102  	if !r.allow(repo) {
   103  		return nil, ociregistry.ErrDenied
   104  	}
   105  	return r.r.PushBlobChunked(ctx, repo, chunkSize)
   106  }
   107  
   108  func (r *selectRegistry) PushBlobChunkedResume(ctx context.Context, repo, id string, offset int64, chunkSize int) (ociregistry.BlobWriter, error) {
   109  	if !r.allow(repo) {
   110  		return nil, ociregistry.ErrDenied
   111  	}
   112  	return r.r.PushBlobChunkedResume(ctx, repo, id, offset, chunkSize)
   113  }
   114  
   115  func (r *selectRegistry) MountBlob(ctx context.Context, fromRepo, toRepo string, digest ociregistry.Digest) (ociregistry.Descriptor, error) {
   116  	if !r.allow(toRepo) {
   117  		return ociregistry.Descriptor{}, ociregistry.ErrDenied
   118  	}
   119  	if !r.allow(fromRepo) {
   120  		return ociregistry.Descriptor{}, ociregistry.ErrNameUnknown
   121  	}
   122  	return r.r.MountBlob(ctx, fromRepo, toRepo, digest)
   123  }
   124  
   125  func (r *selectRegistry) PushManifest(ctx context.Context, repo string, tag string, contents []byte, mediaType string) (ociregistry.Descriptor, error) {
   126  	if !r.allow(repo) {
   127  		return ociregistry.Descriptor{}, ociregistry.ErrDenied
   128  	}
   129  	return r.r.PushManifest(ctx, repo, tag, contents, mediaType)
   130  }
   131  
   132  func (r *selectRegistry) DeleteBlob(ctx context.Context, repo string, digest ociregistry.Digest) error {
   133  	if !r.allow(repo) {
   134  		return ociregistry.ErrNameUnknown
   135  	}
   136  	return r.r.DeleteBlob(ctx, repo, digest)
   137  }
   138  
   139  func (r *selectRegistry) DeleteManifest(ctx context.Context, repo string, digest ociregistry.Digest) error {
   140  	if !r.allow(repo) {
   141  		return ociregistry.ErrNameUnknown
   142  	}
   143  	return r.r.DeleteManifest(ctx, repo, digest)
   144  }
   145  
   146  func (r *selectRegistry) DeleteTag(ctx context.Context, repo string, name string) error {
   147  	if !r.allow(repo) {
   148  		return ociregistry.ErrNameUnknown
   149  	}
   150  	return r.r.DeleteTag(ctx, repo, name)
   151  }
   152  
   153  func (r *selectRegistry) Repositories(ctx context.Context, startAfter string) ociregistry.Seq[string] {
   154  	return func(yield func(string, error) bool) {
   155  		// TODO(go1.23): for name, err := range r.r.Repositories(ctx)
   156  		r.r.Repositories(ctx, startAfter)(func(repo string, err error) bool {
   157  			if err != nil {
   158  				yield("", err)
   159  				return false
   160  			}
   161  			if !r.allow(repo) {
   162  				return true
   163  			}
   164  			return yield(repo, nil)
   165  		})
   166  	}
   167  }
   168  
   169  func (r *selectRegistry) Tags(ctx context.Context, repo, startAfter string) ociregistry.Seq[string] {
   170  	if !r.allow(repo) {
   171  		return ociregistry.ErrorIter[string](ociregistry.ErrNameUnknown)
   172  	}
   173  	return r.r.Tags(ctx, repo, startAfter)
   174  }
   175  
   176  func (r *selectRegistry) Referrers(ctx context.Context, repo string, digest ociregistry.Digest, artifactType string) ociregistry.Seq[ociregistry.Descriptor] {
   177  	if !r.allow(repo) {
   178  		return ociregistry.ErrorIter[ociregistry.Descriptor](ociregistry.ErrNameUnknown)
   179  	}
   180  	return r.r.Referrers(ctx, repo, digest, artifactType)
   181  }
   182  

View as plain text