@@ -3,6 +3,7 @@ package middleware
33import (
44 "fmt"
55 "net/http"
6+ "regexp"
67
78 "github.com/CMSgov/bcda-app/bcda/auth"
89 "github.com/CMSgov/bcda-app/bcda/responseutils"
@@ -34,14 +35,10 @@ func SecurityHeader(next http.Handler) http.Handler {
3435func ACOEnabled (cfg * service.Config ) func (next http.Handler ) http.Handler {
3536 return func (next http.Handler ) http.Handler {
3637 fn := func (w http.ResponseWriter , r * http.Request ) {
37- ctx := r .Context ()
38- ad , ok := ctx .Value (auth .AuthDataContextKey ).(auth.AuthData )
38+ ad , ok := handleAuthData (r )
3939 if ! ok {
40- // We cannot get the correct FHIR response writer from here, so
41- // return a non-FHIR-compliant HTTP response
42- logger := log .GetCtxLogger (ctx )
43- logger .WithField ("resp_status" , http .StatusInternalServerError ).Error ("AuthData should be set before calling this handler" )
4440 http .Error (w , "Internal Server Error" , http .StatusInternalServerError )
41+ return
4542 }
4643
4744 rw , _ := getResponseWriterFromRequestPath (w , r )
@@ -50,8 +47,8 @@ func ACOEnabled(cfg *service.Config) func(next http.Handler) http.Handler {
5047 }
5148
5249 if cfg .IsACODisabled (ad .CMSID ) {
53- ctx , _ = log .WriteWarnWithFields (
54- ctx ,
50+ ctx , _ : = log .WriteWarnWithFields (
51+ r . Context () ,
5552 fmt .Sprintf ("%s: Failed to complete request, CMSID %s is not enabled" , responseutils .UnauthorizedErr , ad .CMSID ),
5653 logrus.Fields {"resp_status" : http .StatusUnauthorized },
5754 )
@@ -68,13 +65,8 @@ func ACOEnabled(cfg *service.Config) func(next http.Handler) http.Handler {
6865func V3AccessControl (cfg * service.Config ) func (next http.Handler ) http.Handler {
6966 return func (next http.Handler ) http.Handler {
7067 fn := func (w http.ResponseWriter , r * http.Request ) {
71- ctx := r .Context ()
72- ad , ok := ctx .Value (auth .AuthDataContextKey ).(auth.AuthData )
68+ ad , ok := handleAuthData (r )
7369 if ! ok {
74- // We cannot get the correct FHIR response writer from here, so
75- // return a non-FHIR-compliant HTTP response
76- logger := log .GetCtxLogger (ctx )
77- logger .WithField ("resp_status" , http .StatusInternalServerError ).Error ("AuthData should be set before calling this handler" )
7870 http .Error (w , "Internal Server Error" , http .StatusInternalServerError )
7971 return
8072 }
@@ -85,8 +77,8 @@ func V3AccessControl(cfg *service.Config) func(next http.Handler) http.Handler {
8577 }
8678
8779 if ! cfg .IsACOV3Enabled (ad .CMSID ) {
88- ctx , _ = log .WriteWarnWithFields (
89- ctx ,
80+ ctx , _ : = log .WriteWarnWithFields (
81+ r . Context () ,
9082 fmt .Sprintf ("%s: Failed to begin v3 request, CMSID %s does not have v3 access" , responseutils .UnauthorizedErr , ad .CMSID ),
9183 logrus.Fields {"resp_status" : http .StatusForbidden },
9284 )
@@ -99,3 +91,60 @@ func V3AccessControl(cfg *service.Config) func(next http.Handler) http.Handler {
9991 return http .HandlerFunc (fn )
10092 }
10193}
94+
95+ func V1V2DenyControl (cfg * service.Config ) func (next http.Handler ) http.Handler {
96+ return func (next http.Handler ) http.Handler {
97+ fn := func (w http.ResponseWriter , r * http.Request ) {
98+ ad , ok := handleAuthData (r )
99+ if ! ok {
100+ http .Error (w , "Internal Server Error" , http .StatusInternalServerError )
101+ return
102+ }
103+
104+ rw , _ := getResponseWriterFromRequestPath (w , r )
105+ if rw == nil {
106+ return
107+ }
108+
109+ if isACOV1V2DeniedAccess (cfg , ad .CMSID ) {
110+ ctx , _ := log .WriteWarnWithFields (
111+ r .Context (),
112+ fmt .Sprintf ("%s: Failed to begin v1/v2 request, CMSID %s does not have v1/v2 access" , responseutils .UnauthorizedErr , ad .CMSID ),
113+ logrus.Fields {"resp_status" : http .StatusForbidden },
114+ )
115+ rw .OpOutcome (ctx , w , http .StatusForbidden , responseutils .UnauthorizedErr , "v1 nor v2 access not enabled for this ACO" )
116+ return
117+ }
118+
119+ next .ServeHTTP (w , r )
120+ }
121+
122+ return http .HandlerFunc (fn )
123+ }
124+ }
125+
126+ func handleAuthData (r * http.Request ) (auth.AuthData , bool ) {
127+ ctx := r .Context ()
128+ ad , ok := ctx .Value (auth .AuthDataContextKey ).(auth.AuthData )
129+ if ! ok {
130+ // We cannot get the correct FHIR response writer from here, so
131+ // return a non-FHIR-compliant HTTP response
132+ logger := log .GetCtxLogger (ctx )
133+ logger .WithField ("resp_status" , http .StatusInternalServerError ).Error ("AuthData should be set before calling this handler" )
134+
135+ return ad , false
136+ }
137+
138+ return ad , true
139+ }
140+
141+ func isACOV1V2DeniedAccess (cfg * service.Config , ACOID string ) bool {
142+ for _ , str := range cfg .V1V2DenyRegexes {
143+ regex := regexp .MustCompile (str )
144+ if regex .MatchString (ACOID ) {
145+ return true
146+ }
147+ }
148+
149+ return false
150+ }
0 commit comments