Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert Traffic Ops into a Service Oriented architecture(SOA) product #6754

Merged
merged 19 commits into from
May 10, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions docs/source/admin/traffic_ops.rst
Original file line number Diff line number Diff line change
Expand Up @@ -600,9 +600,11 @@ This file deals with the configuration parameters of running Traffic Ops as a re

:path: The endpoint that will be served by the backend, for example, `api/4.0/foo`.
:method: The HTTP method for the above mentioned path, for example, `GET` or `PUT`.
srijeet0406 marked this conversation as resolved.
Show resolved Hide resolved
:route_id: The integral identifier for the new route being added.
:routeId: The integral identifier for the new route being added.
:hosts: An array of the hosts and ports where the request (if matched) needs to be forwarded to, for example, `cdn-foo-backend-service-host:9090`.
srijeet0406 marked this conversation as resolved.
Show resolved Hide resolved
:insecure: A boolean specifying whether or not to enable `InsecureSkipVerify`.
:insecure: A boolean specifying whether or not to enable `InsecureSkipVerify`. This is an optional parameter, defaulting to `false` when not present.
srijeet0406 marked this conversation as resolved.
Show resolved Hide resolved
:privLevel: An integer designating the minimum privilege level required to use this API route.
srijeet0406 marked this conversation as resolved.
Show resolved Hide resolved
:permissions: An array of permissions(strings) specifying the permissions required by the user to use this API route.
srijeet0406 marked this conversation as resolved.
Show resolved Hide resolved
:opts: A collection of key value pairs to control how the requests should be forwarded/ handled, for example, `"alg": "roundrobin"`. Currently, only `roundrobin` is supported (which is also the default if nothing is specified) by Traffic Ops.
srijeet0406 marked this conversation as resolved.
Show resolved Hide resolved

Example backends.conf
Expand Down
18 changes: 15 additions & 3 deletions traffic_ops/app/conf/backends.conf
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,33 @@
"localhost:8445"
],
"insecure": true,
"privLevel": 10,
"permissions": [
"CDN:READ",
"CDN:WRITE"
],
"routeId": 123456,
"opts": {
"alg": "roundrobin"
}
},
{
"path": "/api/4.0/bar",
"path": "/api/4.0/foos",
"method": "GET",
"hosts": [
"localhost:8444",
"localhost:9090"
"localhost:8445"
],
"insecure": true,
"privLevel": 10,
"permissions": [
"CDN:READ",
"CDN:WRITE"
],
"routeId": 123457,
"opts": {
"alg": "roundrobin"
}
}
]
}
}
srijeet0406 marked this conversation as resolved.
Show resolved Hide resolved
18 changes: 15 additions & 3 deletions traffic_ops/app/conf/production/backends.conf
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,33 @@
"localhost:8445"
],
"insecure": true,
"privLevel": 10,
"permissions": [
"CDN:READ",
"CDN:WRITE"
],
"routeId": 123456,
"opts": {
"alg": "roundrobin"
}
},
{
"path": "/api/4.0/bar",
"path": "/api/4.0/foos",
"method": "GET",
"hosts": [
"localhost:8444",
"localhost:9090"
"localhost:8445"
],
"insecure": true,
"privLevel": 10,
"permissions": [
"CDN:READ",
"CDN:WRITE"
],
"routeId": 123457,
"opts": {
"alg": "roundrobin"
}
}
]
}
}
16 changes: 9 additions & 7 deletions traffic_ops/traffic_ops_golang/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,15 @@ type Options struct {
}

type BackendRoute struct {
Path string `json:"path"`
Method string `json:"method"`
Hosts []string `json:"hosts"`
Opts Options `json:"opts"`
ID int `json:"route_id"`
Insecure bool `json:"insecure"`
Index int
Path string `json:"path"`
Method string `json:"method"`
Hosts []string `json:"hosts"`
Opts Options `json:"opts"`
ID int `json:"routeId"`
Insecure bool `json:"insecure"`
Permissions []string `json:"permissions"`
PrivLevel int `json:"privLevel"`
Index int
}

type BackendConfig struct {
Expand Down
8 changes: 8 additions & 0 deletions traffic_ops/traffic_ops_golang/routing/middleware/wrappers.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,14 @@ func NotImplementedHandler() http.Handler {
})
}

func BackendErrorHandler(code int, userErr error, sysErr error) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set(rfc.ContentType, rfc.ApplicationJSON)
w.WriteHeader(code)
api.HandleErr(w, r, nil, code, userErr, sysErr)
})
}

// DisabledRouteHandler returns a http.Handler which returns a HTTP 5xx code to the client, and an error message indicating the route is currently disabled.
// This is used for routes which have been disabled via configuration. See config.ConfigTrafficOpsGolang.RoutingBlacklist.DisabledRoutes.
func DisabledRouteHandler() http.Handler {
Expand Down
37 changes: 27 additions & 10 deletions traffic_ops/traffic_ops_golang/routing/routing.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,17 +338,18 @@ func Handler(
routeCtx = context.WithValue(routeCtx, api.PathParamsKey, map[string]string{})
r = r.WithContext(routeCtx)
r.Header.Add(middleware.RouteID, strconv.Itoa(backendRoute.ID))
srijeet0406 marked this conversation as resolved.
Show resolved Hide resolved
userErr, sysErr, code := HandleBackendRoute(cfg.Secrets[0], w, r)
userErr, sysErr, code := HandleBackendRoute(cfg, backendRoute, w, r)
if userErr != nil || sysErr != nil {
w.WriteHeader(code)
api.HandleErr(w, r, nil, code, userErr, sysErr)
h2 := middleware.WrapAccessLog(cfg.Secrets[0], middleware.BackendErrorHandler(code, userErr, sysErr))
h2.ServeHTTP(w, r)
return
}
backendHandler := middleware.WrapAccessLog(cfg.Secrets[0], rp)
backendHandler.ServeHTTP(w, r)
return
} else {
api.HandleErr(w, r, nil, http.StatusBadRequest, errors.New("only an algorithm of roundrobin is supported by the backend options currently"), nil)
h2 := middleware.WrapAccessLog(cfg.Secrets[0], middleware.BackendErrorHandler(http.StatusBadRequest, errors.New("only an algorithm of roundrobin is supported by the backend options currently"), nil))
h2.ServeHTTP(w, r)
return
}
}
Expand All @@ -359,20 +360,36 @@ func Handler(
}

// HandleBackendRoute does all the pre processing for the backend routes.
func HandleBackendRoute(secret string, w http.ResponseWriter, r *http.Request) (error, error, int) {
func HandleBackendRoute(cfg *config.Config, route config.BackendRoute, w http.ResponseWriter, r *http.Request) (error, error, int) {
var userErr, sysErr error
var errCode int
var user auth.CurrentUser
var inf *api.APIInfo

user, userErr, sysErr, errCode = api.GetUserFromReq(w, r, secret)
user, userErr, sysErr, errCode = api.GetUserFromReq(w, r, cfg.Secrets[0])
if userErr != nil || sysErr != nil {
return userErr, sysErr, errCode
}
// Todo: change this to check the actual priv levels
// Todo: add permission checks
if user.PrivLevel < auth.PrivLevelReadOnly {
return errors.New("forbidden"), nil, http.StatusForbidden
v := api.GetRequestedAPIVersion(r.URL.Path)
srijeet0406 marked this conversation as resolved.
Show resolved Hide resolved
if v == nil {
return errors.New("couldn't get a valid version from the requested path"), nil, http.StatusBadRequest
}
if v.Major < 4 {
if user.PrivLevel < route.PrivLevel {
return errors.New("forbidden"), nil, http.StatusForbidden
}
} else {
if !cfg.RoleBasedPermissions {
if user.PrivLevel < route.PrivLevel {
return errors.New("forbidden"), nil, http.StatusForbidden
}
} else {
missingPerms := user.MissingPermissions(route.Permissions...)
if len(missingPerms) != 0 {
msg := strings.Join(missingPerms, ", ")
return fmt.Errorf("missing required Permissions: %s", msg), nil, http.StatusForbidden
}
}
}
api.AddUserToReq(r, user)

Expand Down