github.com/cs3org/reva/v2@v2.27.7/internal/http/interceptors/providerauthorizer/providerauthorizer.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 providerauthorizer
    20  
    21  import (
    22  	"fmt"
    23  	"net/http"
    24  	"net/url"
    25  	"strings"
    26  
    27  	ocmprovider "github.com/cs3org/go-cs3apis/cs3/ocm/provider/v1beta1"
    28  	"github.com/cs3org/reva/v2/pkg/appctx"
    29  	ctxpkg "github.com/cs3org/reva/v2/pkg/ctx"
    30  	"github.com/cs3org/reva/v2/pkg/ocm/provider"
    31  	"github.com/cs3org/reva/v2/pkg/ocm/provider/authorizer/registry"
    32  	"github.com/cs3org/reva/v2/pkg/rhttp/global"
    33  	"github.com/cs3org/reva/v2/pkg/rhttp/router"
    34  	"github.com/cs3org/reva/v2/pkg/utils"
    35  	"github.com/mitchellh/mapstructure"
    36  )
    37  
    38  type config struct {
    39  	Driver  string                            `mapstructure:"driver"`
    40  	Drivers map[string]map[string]interface{} `mapstructure:"drivers"`
    41  }
    42  
    43  func (c *config) init() {
    44  	if c.Driver == "" {
    45  		c.Driver = "json"
    46  	}
    47  }
    48  
    49  func getDriver(c *config) (provider.Authorizer, error) {
    50  	if f, ok := registry.NewFuncs[c.Driver]; ok {
    51  		return f(c.Drivers[c.Driver])
    52  	}
    53  
    54  	return nil, fmt.Errorf("driver %s not found for provider authorizer", c.Driver)
    55  }
    56  
    57  // New returns a new HTTP middleware that verifies that the provider is registered in OCM.
    58  func New(m map[string]interface{}, unprotected []string, ocmPrefix string) (global.Middleware, error) {
    59  
    60  	if ocmPrefix == "" {
    61  		ocmPrefix = "ocm"
    62  	}
    63  
    64  	conf := &config{}
    65  	if err := mapstructure.Decode(m, conf); err != nil {
    66  		return nil, err
    67  	}
    68  	conf.init()
    69  
    70  	authorizer, err := getDriver(conf)
    71  	if err != nil {
    72  		return nil, err
    73  	}
    74  
    75  	handler := func(h http.Handler) http.Handler {
    76  		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    77  
    78  			ctx := r.Context()
    79  			log := appctx.GetLogger(ctx)
    80  			head, _ := router.ShiftPath(r.URL.Path)
    81  
    82  			if r.Method == "OPTIONS" || head != ocmPrefix || utils.Skip(r.URL.Path, unprotected) {
    83  				log.Info().Msg("skipping provider authorizer check for: " + r.URL.Path)
    84  				h.ServeHTTP(w, r)
    85  				return
    86  			}
    87  
    88  			userIdp := ctxpkg.ContextMustGetUser(ctx).Id.Idp
    89  			if !(strings.Contains(userIdp, "://")) {
    90  				userIdp = "https://" + userIdp
    91  			}
    92  			userIdpURL, err := url.Parse(userIdp)
    93  			if err != nil {
    94  				log.Error().Err(err).Msg("error parsing user idp in provider authorizer")
    95  				w.WriteHeader(http.StatusUnauthorized)
    96  				return
    97  			}
    98  
    99  			err = authorizer.IsProviderAllowed(ctx, &ocmprovider.ProviderInfo{
   100  				Domain: userIdpURL.Hostname(),
   101  			})
   102  			if err != nil {
   103  				log.Error().Err(err).Msg("provider not registered in OCM")
   104  				w.WriteHeader(http.StatusUnauthorized)
   105  				return
   106  			}
   107  
   108  			h.ServeHTTP(w, r)
   109  		})
   110  	}
   111  
   112  	return handler, nil
   113  
   114  }