@@ -10,6 +10,10 @@ import (
1010 "golang.org/x/net/webdav"
1111
1212 docker "github.com/fsouza/go-dockerclient"
13+
14+ kauthapi "k8s.io/kubernetes/pkg/apis/authorization"
15+ krestclient "k8s.io/kubernetes/pkg/client/restclient"
16+ kclient "k8s.io/kubernetes/pkg/client/unversioned"
1317)
1418
1519const (
@@ -55,29 +59,93 @@ func (s *webdavImageServer) ServeImage(imageMetadata *docker.Image) error {
5559 w .Write ([]byte ("ok\n " ))
5660 })
5761
58- http .HandleFunc (s .opts .APIURL , func (w http.ResponseWriter , r * http.Request ) {
62+ http .HandleFunc (s .opts .APIURL , s . handlerFuncAuth ( func (w http.ResponseWriter , r * http.Request ) {
5963 body , err := json .MarshalIndent (s .opts .APIVersions , "" , " " )
6064 if err != nil {
6165 http .Error (w , err .Error (), http .StatusInternalServerError )
6266 return
6367 }
6468 w .Write (body )
65- })
69+ }))
6670
67- http .HandleFunc (s .opts .MetadataURL , func (w http.ResponseWriter , r * http.Request ) {
71+ http .HandleFunc (s .opts .MetadataURL , s . handlerFuncAuth ( func (w http.ResponseWriter , r * http.Request ) {
6872 body , err := json .MarshalIndent (imageMetadata , "" , " " )
6973 if err != nil {
7074 http .Error (w , err .Error (), http .StatusInternalServerError )
7175 return
7276 }
7377 w .Write (body )
74- })
78+ }))
7579
76- http .Handle (s .opts .ContentURL , & webdav.Handler {
80+ http .Handle (s .opts .ContentURL , s . newAuthenticatedHandler ( & webdav.Handler {
7781 Prefix : s .opts .ContentURL ,
7882 FileSystem : webdav .Dir (servePath ),
7983 LockSystem : webdav .NewMemLS (),
80- })
84+ }))
8185
8286 return http .ListenAndServe (s .opts .ServePath , nil )
8387}
88+
89+ func (s * webdavImageServer ) authenticate (r * http.Request ) (bool , error ) {
90+ authenticator , ok := map [AuthenticationType ]func (r * http.Request ) (bool , error ){
91+ AllowAll : allowAll ,
92+ KubernetesToken : kubernetesTokenAuth ,
93+ }[s .opts .AuthType ]
94+ if ! ok {
95+ return false , fmt .Errorf ("%s is not a recognize authentication method" , s .opts .AuthType )
96+ }
97+ return authenticator (r )
98+ }
99+
100+ func allowAll (r * http.Request ) (bool , error ) {
101+ return true , nil
102+ }
103+
104+ func kubernetesTokenAuth (r * http.Request ) (bool , error ) {
105+ conf , err := krestclient .InClusterConfig ()
106+ if err != nil {
107+ return false , err
108+ }
109+ conf .BearerToken = r .Header .Get ("Authorization" )
110+ kc , err := kclient .New (conf )
111+ if err != nil {
112+ return false , err
113+ }
114+ result := & kauthapi.SubjectAccessReview {}
115+ sar := & kauthapi.SubjectAccessReview {}
116+ sar .Kind = "SubjectAccessReview"
117+ sar .APIVersion = "v1"
118+ sar .Spec .ResourceAttributes .Verb = "GET"
119+ sar .Spec .ResourceAttributes .Resource = "images"
120+ err = kc .Get ().Resource ("subjectAccessReview" ).Body (sar ).Do ().Into (result )
121+ if err != nil {
122+ return false , err
123+ }
124+ return result .Status .Allowed , nil
125+ }
126+
127+ func (s * webdavImageServer ) handlerFuncAuth (f http.HandlerFunc ) http.HandlerFunc {
128+ return func (w http.ResponseWriter , r * http.Request ) {
129+ if allowed , err := s .authenticate (r ); allowed && err == nil {
130+ f (w , r )
131+ } else {
132+ if err != nil {
133+ http .Error (w , err .Error (), http .StatusInternalServerError )
134+ } else {
135+ http .Error (w , "Unauthorazied Access!" , http .StatusForbidden )
136+ }
137+ }
138+ }
139+ }
140+
141+ type authenticatedHandler struct {
142+ serveHttp func (http.ResponseWriter , * http.Request )
143+ }
144+
145+ func (ah * authenticatedHandler ) ServeHTTP (w http.ResponseWriter , r * http.Request ) {
146+ ah .serveHttp (w , r )
147+ }
148+
149+ func (s * webdavImageServer ) newAuthenticatedHandler (h http.Handler ) http.Handler {
150+ return & authenticatedHandler {serveHttp : s .handlerFuncAuth (h .ServeHTTP )}
151+ }
0 commit comments