cubefs

Форк
0
/
http_server.go 
175 строк · 5.2 Кб
1
// Copyright 2018 The CubeFS Authors.
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
12
// implied. See the License for the specific language governing
13
// permissions and limitations under the License.
14

15
package authnode
16

17
import (
18
	"crypto/tls"
19
	"net/http"
20
	"net/http/httputil"
21
	"time"
22

23
	"github.com/cubefs/cubefs/proto"
24
	"github.com/cubefs/cubefs/util/cryptoutil"
25
	"github.com/cubefs/cubefs/util/log"
26
)
27

28
func (m *Server) startHTTPService() {
29
	go func() {
30
		m.handleFunctions()
31
		if m.cluster.PKIKey.EnableHTTPS {
32
			// not use PKI to verify client certificate
33
			// Instead, we use client secret key for authentication
34
			cfg := &tls.Config{
35
				MinVersion: tls.VersionTLS12,
36
				// ClientAuth: tls.RequireAndVerifyClientCert,
37
				// ClientCAs:  caCertPool,
38
			}
39
			srv := &http.Server{
40
				Addr:         colonSplit + m.port,
41
				TLSConfig:    cfg,
42
				ReadTimeout:  5 * time.Minute,
43
				WriteTimeout: 5 * time.Minute,
44
			}
45
			if err := srv.ListenAndServeTLS("/app/server.crt", "/app/server.key"); err != nil {
46
				log.LogErrorf("action[startHTTPService] failed,err[%v]", err)
47
				panic(err)
48
			}
49

50
		} else {
51
			if err := http.ListenAndServe(colonSplit+m.port, nil); err != nil {
52
				log.LogErrorf("action[startHTTPService] failed,err[%v]", err)
53
				panic(err)
54
			}
55
		}
56
	}()
57
	return
58
}
59

60
func (m *Server) newAuthProxy() *AuthProxy {
61
	var (
62
		authProxy AuthProxy
63
		err       error
64
	)
65
	if m.cluster.PKIKey.EnableHTTPS {
66
		if authProxy.client, err = cryptoutil.CreateClientX(&m.cluster.PKIKey.AuthRootPublicKey); err != nil {
67
			panic(err)
68
		}
69
	} else {
70
		authProxy.reverseProxy = &httputil.ReverseProxy{
71
			Director: func(request *http.Request) {
72
				request.URL.Scheme = "http"
73
				request.URL.Host = m.leaderInfo.addr
74
			},
75
		}
76
	}
77
	return &authProxy
78
}
79

80
func (m *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
81
	log.LogInfof("URL[%v],remoteAddr[%v]", r.URL, r.RemoteAddr)
82
	switch r.URL.Path {
83
	case proto.ClientGetTicket:
84
		m.getTicket(w, r)
85
	case proto.AdminCreateKey:
86
		fallthrough
87
	case proto.AdminGetKey:
88
		fallthrough
89
	case proto.AdminDeleteKey:
90
		fallthrough
91
	case proto.AdminAddCaps:
92
		fallthrough
93
	case proto.AdminDeleteCaps:
94
		fallthrough
95
	case proto.AdminGetCaps:
96
		m.apiAccessEntry(w, r)
97
	case proto.AdminAddRaftNode:
98
		fallthrough
99
	case proto.AdminRemoveRaftNode:
100
		m.raftNodeOp(w, r)
101
	case proto.OSAddCaps:
102
		fallthrough
103
	case proto.OSDeleteCaps:
104
		fallthrough
105
	case proto.OSGetCaps:
106
		m.osCapsOp(w, r)
107
	default:
108
		sendErrReply(w, r, &proto.HTTPAuthReply{Code: proto.ErrCodeParamError, Msg: "Invalid requst URL"})
109
	}
110
}
111

112
func (m *Server) handleFunctions() {
113
	http.HandleFunc(proto.ClientGetTicket, m.getTicket)
114
	http.Handle(proto.AdminCreateKey, m.handlerWithInterceptor())
115
	http.Handle(proto.AdminGetKey, m.handlerWithInterceptor())
116
	http.Handle(proto.AdminDeleteKey, m.handlerWithInterceptor())
117
	http.Handle(proto.AdminAddCaps, m.handlerWithInterceptor())
118
	http.Handle(proto.AdminDeleteCaps, m.handlerWithInterceptor())
119
	http.Handle(proto.AdminGetCaps, m.handlerWithInterceptor())
120
	http.Handle(proto.AdminAddRaftNode, m.handlerWithInterceptor())
121
	http.Handle(proto.AdminRemoveRaftNode, m.handlerWithInterceptor())
122
	http.Handle(proto.OSAddCaps, m.handlerWithInterceptor())
123
	http.Handle(proto.OSDeleteCaps, m.handlerWithInterceptor())
124
	http.Handle(proto.OSGetCaps, m.handlerWithInterceptor())
125
	return
126
}
127

128
func (m *Server) handlerWithInterceptor() http.Handler {
129
	return http.HandlerFunc(
130
		func(w http.ResponseWriter, r *http.Request) {
131
			if m.partition.IsRaftLeader() {
132
				if m.metaReady {
133
					m.ServeHTTP(w, r)
134
					return
135
				}
136
				log.LogWarnf("action[handlerWithInterceptor] leader meta has not ready")
137
				http.Error(w, m.leaderInfo.addr, http.StatusBadRequest)
138
				return
139
			}
140
			if m.leaderInfo.addr == "" {
141
				log.LogErrorf("action[handlerWithInterceptor] no leader,request[%v]", r.URL)
142
				http.Error(w, "no leader", http.StatusBadRequest)
143
				return
144
			}
145
			m.proxy(w, r)
146
		})
147
}
148

149
func (m *Server) proxy(w http.ResponseWriter, r *http.Request) {
150
	if m.cluster.PKIKey.EnableHTTPS {
151
		var (
152
			plaintext []byte
153
			err       error
154
			res       []byte
155
			jobj      proto.HTTPAuthReply
156
		)
157
		target := "https://" + m.leaderInfo.addr + r.URL.Path
158
		if plaintext, err = m.extractClientReqInfo(r); err != nil {
159
			sendErrReply(w, r, &proto.HTTPAuthReply{Code: proto.ErrCodeParamError, Msg: err.Error()})
160
			return
161
		}
162
		res, err = proto.SendBytes(m.authProxy.client, target, plaintext)
163
		if err != nil {
164
			sendErrReply(w, r, &proto.HTTPAuthReply{Code: proto.ErrCodeAuthReqRedirectError, Msg: "[proxy] failed: " + err.Error()})
165
			return
166
		}
167
		if jobj, err = proto.ParseAuthReply(res); err != nil {
168
			sendErrReply(w, r, &proto.HTTPAuthReply{Code: proto.ErrCodeAuthReqRedirectError, Msg: "Target Server failed: " + err.Error()})
169
			return
170
		}
171
		sendOkReply(w, r, newSuccessHTTPAuthReply(jobj.Data))
172
	} else {
173
		m.authProxy.reverseProxy.ServeHTTP(w, r)
174
	}
175
}
176

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.