github.com/cs3org/reva/v2@v2.27.7/internal/grpc/interceptors/readonly/readonly.go (about)

     1  // Copyright 2018-2021 CERN
     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  // In applying this license, CERN does not waive the privileges and immunities
    16  // granted to it by virtue of its status as an Intergovernmental Organization
    17  // or submit itself to any jurisdiction.
    18  
    19  package readonly
    20  
    21  import (
    22  	"context"
    23  
    24  	provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
    25  	registry "github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1"
    26  	"github.com/cs3org/reva/v2/pkg/appctx"
    27  	"github.com/cs3org/reva/v2/pkg/rgrpc"
    28  	rstatus "github.com/cs3org/reva/v2/pkg/rgrpc/status"
    29  	"google.golang.org/grpc"
    30  	"google.golang.org/grpc/codes"
    31  	"google.golang.org/grpc/status"
    32  )
    33  
    34  const (
    35  	defaultPriority = 200
    36  )
    37  
    38  func init() {
    39  	rgrpc.RegisterUnaryInterceptor("readonly", NewUnary)
    40  }
    41  
    42  // NewUnary returns a new unary interceptor
    43  // that checks grpc calls and blocks write requests.
    44  func NewUnary(map[string]interface{}) (grpc.UnaryServerInterceptor, int, error) {
    45  	return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
    46  		log := appctx.GetLogger(ctx)
    47  
    48  		switch req.(type) {
    49  		// handle known non-write request types
    50  		case *provider.GetHomeRequest,
    51  			*provider.GetPathRequest,
    52  			*provider.GetQuotaRequest,
    53  			*registry.GetStorageProvidersRequest,
    54  			*provider.InitiateFileDownloadRequest,
    55  			*provider.ListFileVersionsRequest,
    56  			*provider.ListGrantsRequest,
    57  			*provider.ListRecycleRequest:
    58  			return handler(ctx, req)
    59  		case *provider.ListContainerRequest:
    60  			resp, err := handler(ctx, req)
    61  			if listResp, ok := resp.(*provider.ListContainerResponse); ok && listResp.Infos != nil {
    62  				for _, info := range listResp.Infos {
    63  					// use the existing PermissionsSet and change the writes to false
    64  					if info.PermissionSet != nil {
    65  						info.PermissionSet.AddGrant = false
    66  						info.PermissionSet.CreateContainer = false
    67  						info.PermissionSet.Delete = false
    68  						info.PermissionSet.InitiateFileUpload = false
    69  						info.PermissionSet.Move = false
    70  						info.PermissionSet.RemoveGrant = false
    71  						info.PermissionSet.PurgeRecycle = false
    72  						info.PermissionSet.RestoreFileVersion = false
    73  						info.PermissionSet.RestoreRecycleItem = false
    74  						info.PermissionSet.UpdateGrant = false
    75  					}
    76  				}
    77  			}
    78  			return resp, err
    79  		case *provider.StatRequest:
    80  			resp, err := handler(ctx, req)
    81  			if statResp, ok := resp.(*provider.StatResponse); ok && statResp.Info != nil && statResp.Info.PermissionSet != nil {
    82  				// use the existing PermissionsSet and change the writes to false
    83  				statResp.Info.PermissionSet.AddGrant = false
    84  				statResp.Info.PermissionSet.CreateContainer = false
    85  				statResp.Info.PermissionSet.Delete = false
    86  				statResp.Info.PermissionSet.InitiateFileUpload = false
    87  				statResp.Info.PermissionSet.Move = false
    88  				statResp.Info.PermissionSet.RemoveGrant = false
    89  				statResp.Info.PermissionSet.PurgeRecycle = false
    90  				statResp.Info.PermissionSet.RestoreFileVersion = false
    91  				statResp.Info.PermissionSet.RestoreRecycleItem = false
    92  				statResp.Info.PermissionSet.UpdateGrant = false
    93  			}
    94  			return resp, err
    95  		// Don't allow the following requests types
    96  		case *provider.AddGrantRequest:
    97  			return &provider.AddGrantResponse{
    98  				Status: rstatus.NewPermissionDenied(ctx, nil, "permission denied: tried to add grant on readonly storage"),
    99  			}, nil
   100  		case *provider.CreateContainerRequest:
   101  			return &provider.CreateContainerResponse{
   102  				Status: rstatus.NewPermissionDenied(ctx, nil, "permission denied: tried to create resource on read-only storage"),
   103  			}, nil
   104  		case *provider.TouchFileRequest:
   105  			return &provider.TouchFileResponse{
   106  				Status: rstatus.NewPermissionDenied(ctx, nil, "permission denied: tried to create resource on read-only storage"),
   107  			}, nil
   108  		case *provider.CreateHomeRequest:
   109  			return &provider.CreateHomeResponse{
   110  				Status: rstatus.NewPermissionDenied(ctx, nil, "permission denied: tried to create home on readonly storage"),
   111  			}, nil
   112  		case *provider.DeleteRequest:
   113  			return &provider.DeleteResponse{
   114  				Status: rstatus.NewPermissionDenied(ctx, nil, "permission denied: tried to delete resource on readonly storage"),
   115  			}, nil
   116  		case *provider.InitiateFileUploadRequest:
   117  			return &provider.InitiateFileUploadResponse{
   118  				Status: rstatus.NewPermissionDenied(ctx, nil, "permission denied: tried to upload resource on readonly storage"),
   119  			}, nil
   120  		case *provider.MoveRequest:
   121  			return &provider.MoveResponse{
   122  				Status: rstatus.NewPermissionDenied(ctx, nil, "permission denied: tried to move resource on readonly storage"),
   123  			}, nil
   124  		case *provider.PurgeRecycleRequest:
   125  			return &provider.PurgeRecycleResponse{
   126  				Status: rstatus.NewPermissionDenied(ctx, nil, "permission denied: tried to purge recycle on readonly storage"),
   127  			}, nil
   128  		case *provider.RemoveGrantRequest:
   129  			return &provider.RemoveGrantResponse{
   130  				Status: rstatus.NewPermissionDenied(ctx, nil, "permission denied: tried to remove grant on readonly storage"),
   131  			}, nil
   132  		case *provider.RestoreRecycleItemRequest:
   133  			return &provider.RestoreRecycleItemResponse{
   134  				Status: rstatus.NewPermissionDenied(ctx, nil, "permission denied: tried to restore recycle item on readonly storage"),
   135  			}, nil
   136  		case *provider.SetArbitraryMetadataRequest:
   137  			return &provider.SetArbitraryMetadataResponse{
   138  				Status: rstatus.NewPermissionDenied(ctx, nil, "permission denied: tried to set arbitrary metadata on readonly storage"),
   139  			}, nil
   140  		case *provider.UnsetArbitraryMetadataRequest:
   141  			return &provider.UnsetArbitraryMetadataResponse{
   142  				Status: rstatus.NewPermissionDenied(ctx, nil, "permission denied: tried to unset arbitrary metadata on readonly storage"),
   143  			}, nil
   144  		// block unknown request types and return error
   145  		default:
   146  			log.Debug().Msg("storage is readonly")
   147  			return nil, status.Errorf(codes.PermissionDenied, "permission denied: tried to execute an unknown operation: %T!", req)
   148  		}
   149  	}, defaultPriority, nil
   150  }