1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
package authz
import (
"context"
"strings"
core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
auth "github.com/envoyproxy/go-control-plane/envoy/service/auth/v3"
types "github.com/envoyproxy/go-control-plane/envoy/type/v3"
"github.com/xlgmokha/x/pkg/log"
"github.com/xlgmokha/x/pkg/x"
status "google.golang.org/genproto/googleapis/rpc/status"
"google.golang.org/grpc/codes"
)
type CheckService struct {
auth.UnimplementedAuthorizationServer
}
func (svc *CheckService) Check(ctx context.Context, request *auth.CheckRequest) (*auth.CheckResponse, error) {
if svc.isAllowed(ctx, request) {
return svc.OK(ctx), nil
}
return svc.Denied(ctx), nil
}
// TODOD:: Replace with a PaC language
func (svc *CheckService) isPublic(ctx context.Context, r *auth.CheckRequest) bool {
allowed := map[string]bool{
"GET:/": true,
"GET:/application.js": true,
"GET:/callback": true,
"GET:/dashboard/nav": true,
"GET:/favicon.ico": true,
"GET:/favicon.png": true,
"GET:/health": true,
"GET:/index.html": true,
"GET:/logo.png": true,
"GET:/signout": true,
"GET:/sparkle": true,
"GET:/sparkles": true,
"POST:/sparkles/restore": true,
}
ok, _ := allowed[strings.Join([]string{
r.Attributes.Request.Http.Method,
r.Attributes.Request.Http.Path,
}, ":")]
return ok
}
func (svc *CheckService) isAllowed(ctx context.Context, r *auth.CheckRequest) bool {
if !svc.validRequest(ctx, r) {
return false
}
log.WithFields(ctx, svc.fieldsFor(r))
return svc.isLoggedIn(ctx, r) || svc.isPublic(ctx, r)
}
func (svc *CheckService) validRequest(ctx context.Context, r *auth.CheckRequest) bool {
return x.IsPresent(r) &&
x.IsPresent(r.Attributes) &&
x.IsPresent(r.Attributes.Request) &&
x.IsPresent(r.Attributes.Request.Http)
}
// TODO:: Replace this naive implementation
func (svc *CheckService) isLoggedIn(ctx context.Context, r *auth.CheckRequest) bool {
return x.IsPresent(r.Attributes.Request.Http.Headers["cookie"])
}
func (svc *CheckService) OK(ctx context.Context) *auth.CheckResponse {
log.WithFields(ctx, log.Fields{"authorized": true})
return &auth.CheckResponse{
Status: &status.Status{
Code: int32(codes.OK),
},
HttpResponse: &auth.CheckResponse_OkResponse{
OkResponse: &auth.OkHttpResponse{
Headers: []*core.HeaderValueOption{},
HeadersToRemove: []string{},
ResponseHeadersToAdd: []*core.HeaderValueOption{},
},
},
}
}
func (svc *CheckService) Denied(ctx context.Context) *auth.CheckResponse {
log.WithFields(ctx, log.Fields{"authorized": false})
return &auth.CheckResponse{
Status: &status.Status{
Code: int32(codes.PermissionDenied),
},
HttpResponse: &auth.CheckResponse_DeniedResponse{
DeniedResponse: &auth.DeniedHttpResponse{
Status: &types.HttpStatus{
Code: types.StatusCode_Unauthorized,
},
Headers: []*core.HeaderValueOption{},
},
},
}
}
func (svc *CheckService) fieldsFor(r *auth.CheckRequest) log.Fields {
return log.Fields{
"id": r.Attributes.Request.Http.Id,
"method": r.Attributes.Request.Http.Method,
"path": r.Attributes.Request.Http.Path,
"host": r.Attributes.Request.Http.Host,
"scheme": r.Attributes.Request.Http.Scheme,
"protocol": r.Attributes.Request.Http.Protocol,
}
}
|