podman

Форк
0
276 строк · 8.8 Кб
1
// Copyright 2015 go-swagger maintainers
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 implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15
package security
16

17
import (
18
	"context"
19
	"net/http"
20
	"strings"
21

22
	"github.com/go-openapi/errors"
23

24
	"github.com/go-openapi/runtime"
25
)
26

27
const (
28
	query  = "query"
29
	header = "header"
30
)
31

32
// HttpAuthenticator is a function that authenticates a HTTP request
33
func HttpAuthenticator(handler func(*http.Request) (bool, interface{}, error)) runtime.Authenticator {
34
	return runtime.AuthenticatorFunc(func(params interface{}) (bool, interface{}, error) {
35
		if request, ok := params.(*http.Request); ok {
36
			return handler(request)
37
		}
38
		if scoped, ok := params.(*ScopedAuthRequest); ok {
39
			return handler(scoped.Request)
40
		}
41
		return false, nil, nil
42
	})
43
}
44

45
// ScopedAuthenticator is a function that authenticates a HTTP request against a list of valid scopes
46
func ScopedAuthenticator(handler func(*ScopedAuthRequest) (bool, interface{}, error)) runtime.Authenticator {
47
	return runtime.AuthenticatorFunc(func(params interface{}) (bool, interface{}, error) {
48
		if request, ok := params.(*ScopedAuthRequest); ok {
49
			return handler(request)
50
		}
51
		return false, nil, nil
52
	})
53
}
54

55
// UserPassAuthentication authentication function
56
type UserPassAuthentication func(string, string) (interface{}, error)
57

58
// UserPassAuthenticationCtx authentication function with context.Context
59
type UserPassAuthenticationCtx func(context.Context, string, string) (context.Context, interface{}, error)
60

61
// TokenAuthentication authentication function
62
type TokenAuthentication func(string) (interface{}, error)
63

64
// TokenAuthenticationCtx authentication function with context.Context
65
type TokenAuthenticationCtx func(context.Context, string) (context.Context, interface{}, error)
66

67
// ScopedTokenAuthentication authentication function
68
type ScopedTokenAuthentication func(string, []string) (interface{}, error)
69

70
// ScopedTokenAuthenticationCtx authentication function with context.Context
71
type ScopedTokenAuthenticationCtx func(context.Context, string, []string) (context.Context, interface{}, error)
72

73
var DefaultRealmName = "API"
74

75
type secCtxKey uint8
76

77
const (
78
	failedBasicAuth secCtxKey = iota
79
	oauth2SchemeName
80
)
81

82
func FailedBasicAuth(r *http.Request) string {
83
	return FailedBasicAuthCtx(r.Context())
84
}
85

86
func FailedBasicAuthCtx(ctx context.Context) string {
87
	v, ok := ctx.Value(failedBasicAuth).(string)
88
	if !ok {
89
		return ""
90
	}
91
	return v
92
}
93

94
func OAuth2SchemeName(r *http.Request) string {
95
	return OAuth2SchemeNameCtx(r.Context())
96
}
97

98
func OAuth2SchemeNameCtx(ctx context.Context) string {
99
	v, ok := ctx.Value(oauth2SchemeName).(string)
100
	if !ok {
101
		return ""
102
	}
103
	return v
104
}
105

106
// BasicAuth creates a basic auth authenticator with the provided authentication function
107
func BasicAuth(authenticate UserPassAuthentication) runtime.Authenticator {
108
	return BasicAuthRealm(DefaultRealmName, authenticate)
109
}
110

111
// BasicAuthRealm creates a basic auth authenticator with the provided authentication function and realm name
112
func BasicAuthRealm(realm string, authenticate UserPassAuthentication) runtime.Authenticator {
113
	if realm == "" {
114
		realm = DefaultRealmName
115
	}
116

117
	return HttpAuthenticator(func(r *http.Request) (bool, interface{}, error) {
118
		if usr, pass, ok := r.BasicAuth(); ok {
119
			p, err := authenticate(usr, pass)
120
			if err != nil {
121
				*r = *r.WithContext(context.WithValue(r.Context(), failedBasicAuth, realm))
122
			}
123
			return true, p, err
124
		}
125
		*r = *r.WithContext(context.WithValue(r.Context(), failedBasicAuth, realm))
126
		return false, nil, nil
127
	})
128
}
129

130
// BasicAuthCtx creates a basic auth authenticator with the provided authentication function with support for context.Context
131
func BasicAuthCtx(authenticate UserPassAuthenticationCtx) runtime.Authenticator {
132
	return BasicAuthRealmCtx(DefaultRealmName, authenticate)
133
}
134

135
// BasicAuthRealmCtx creates a basic auth authenticator with the provided authentication function and realm name with support for context.Context
136
func BasicAuthRealmCtx(realm string, authenticate UserPassAuthenticationCtx) runtime.Authenticator {
137
	if realm == "" {
138
		realm = DefaultRealmName
139
	}
140

141
	return HttpAuthenticator(func(r *http.Request) (bool, interface{}, error) {
142
		if usr, pass, ok := r.BasicAuth(); ok {
143
			ctx, p, err := authenticate(r.Context(), usr, pass)
144
			if err != nil {
145
				ctx = context.WithValue(ctx, failedBasicAuth, realm)
146
			}
147
			*r = *r.WithContext(ctx)
148
			return true, p, err
149
		}
150
		*r = *r.WithContext(context.WithValue(r.Context(), failedBasicAuth, realm))
151
		return false, nil, nil
152
	})
153
}
154

155
// APIKeyAuth creates an authenticator that uses a token for authorization.
156
// This token can be obtained from either a header or a query string
157
func APIKeyAuth(name, in string, authenticate TokenAuthentication) runtime.Authenticator {
158
	inl := strings.ToLower(in)
159
	if inl != query && inl != header {
160
		// panic because this is most likely a typo
161
		panic(errors.New(500, "api key auth: in value needs to be either \"query\" or \"header\"."))
162
	}
163

164
	var getToken func(*http.Request) string
165
	switch inl {
166
	case header:
167
		getToken = func(r *http.Request) string { return r.Header.Get(name) }
168
	case query:
169
		getToken = func(r *http.Request) string { return r.URL.Query().Get(name) }
170
	}
171

172
	return HttpAuthenticator(func(r *http.Request) (bool, interface{}, error) {
173
		token := getToken(r)
174
		if token == "" {
175
			return false, nil, nil
176
		}
177

178
		p, err := authenticate(token)
179
		return true, p, err
180
	})
181
}
182

183
// APIKeyAuthCtx creates an authenticator that uses a token for authorization with support for context.Context.
184
// This token can be obtained from either a header or a query string
185
func APIKeyAuthCtx(name, in string, authenticate TokenAuthenticationCtx) runtime.Authenticator {
186
	inl := strings.ToLower(in)
187
	if inl != query && inl != header {
188
		// panic because this is most likely a typo
189
		panic(errors.New(500, "api key auth: in value needs to be either \"query\" or \"header\"."))
190
	}
191

192
	var getToken func(*http.Request) string
193
	switch inl {
194
	case header:
195
		getToken = func(r *http.Request) string { return r.Header.Get(name) }
196
	case query:
197
		getToken = func(r *http.Request) string { return r.URL.Query().Get(name) }
198
	}
199

200
	return HttpAuthenticator(func(r *http.Request) (bool, interface{}, error) {
201
		token := getToken(r)
202
		if token == "" {
203
			return false, nil, nil
204
		}
205

206
		ctx, p, err := authenticate(r.Context(), token)
207
		*r = *r.WithContext(ctx)
208
		return true, p, err
209
	})
210
}
211

212
// ScopedAuthRequest contains both a http request and the required scopes for a particular operation
213
type ScopedAuthRequest struct {
214
	Request        *http.Request
215
	RequiredScopes []string
216
}
217

218
// BearerAuth for use with oauth2 flows
219
func BearerAuth(name string, authenticate ScopedTokenAuthentication) runtime.Authenticator {
220
	const prefix = "Bearer "
221
	return ScopedAuthenticator(func(r *ScopedAuthRequest) (bool, interface{}, error) {
222
		var token string
223
		hdr := r.Request.Header.Get(runtime.HeaderAuthorization)
224
		if strings.HasPrefix(hdr, prefix) {
225
			token = strings.TrimPrefix(hdr, prefix)
226
		}
227
		if token == "" {
228
			qs := r.Request.URL.Query()
229
			token = qs.Get("access_token")
230
		}
231
		//#nosec
232
		ct, _, _ := runtime.ContentType(r.Request.Header)
233
		if token == "" && (ct == "application/x-www-form-urlencoded" || ct == "multipart/form-data") {
234
			token = r.Request.FormValue("access_token")
235
		}
236

237
		if token == "" {
238
			return false, nil, nil
239
		}
240

241
		rctx := context.WithValue(r.Request.Context(), oauth2SchemeName, name)
242
		*r.Request = *r.Request.WithContext(rctx)
243
		p, err := authenticate(token, r.RequiredScopes)
244
		return true, p, err
245
	})
246
}
247

248
// BearerAuthCtx for use with oauth2 flows with support for context.Context.
249
func BearerAuthCtx(name string, authenticate ScopedTokenAuthenticationCtx) runtime.Authenticator {
250
	const prefix = "Bearer "
251
	return ScopedAuthenticator(func(r *ScopedAuthRequest) (bool, interface{}, error) {
252
		var token string
253
		hdr := r.Request.Header.Get(runtime.HeaderAuthorization)
254
		if strings.HasPrefix(hdr, prefix) {
255
			token = strings.TrimPrefix(hdr, prefix)
256
		}
257
		if token == "" {
258
			qs := r.Request.URL.Query()
259
			token = qs.Get("access_token")
260
		}
261
		//#nosec
262
		ct, _, _ := runtime.ContentType(r.Request.Header)
263
		if token == "" && (ct == "application/x-www-form-urlencoded" || ct == "multipart/form-data") {
264
			token = r.Request.FormValue("access_token")
265
		}
266

267
		if token == "" {
268
			return false, nil, nil
269
		}
270

271
		rctx := context.WithValue(r.Request.Context(), oauth2SchemeName, name)
272
		ctx, p, err := authenticate(rctx, token, r.RequiredScopes)
273
		*r.Request = *r.Request.WithContext(ctx)
274
		return true, p, err
275
	})
276
}
277

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

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

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

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