istio

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

15
package caclient
16

17
import (
18
	"context"
19
	"encoding/json"
20
	"fmt"
21

22
	"google.golang.org/grpc/credentials"
23

24
	"istio.io/istio/pkg/security"
25
	"istio.io/istio/security/pkg/nodeagent/plugin/providers/google/stsclient"
26
	"istio.io/istio/security/pkg/stsservice"
27
	"istio.io/istio/security/pkg/stsservice/server"
28
	"istio.io/istio/security/pkg/stsservice/tokenmanager/google"
29
)
30

31
// TokenProvider is a grpc PerRPCCredentials that can be used to attach a JWT token to each gRPC call.
32
// TokenProvider can be used for XDS, which may involve token exchange through STS.
33
type TokenProvider struct {
34
	opts *security.Options
35
	// TokenProvider can be used for XDS. Because CA is often used with
36
	// external systems and XDS is not often (yet?), many of the security options only apply to CA
37
	// communication. A more proper solution would be to have separate options for CA and XDS, but
38
	// this requires API changes.
39
	forCA bool
40
}
41

42
var _ credentials.PerRPCCredentials = &TokenProvider{}
43

44
// TODO add metrics
45
// TODO change package
46
func NewCATokenProvider(opts *security.Options) *TokenProvider {
47
	return &TokenProvider{opts, true}
48
}
49

50
func NewXDSTokenProvider(opts *security.Options) *TokenProvider {
51
	return &TokenProvider{opts, false}
52
}
53

54
func (t *TokenProvider) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) {
55
	if t == nil {
56
		return nil, nil
57
	}
58
	token, err := t.GetToken()
59
	if err != nil {
60
		return nil, err
61
	}
62
	if token == "" {
63
		return nil, nil
64
	}
65
	if t.opts.TokenManager == nil {
66
		return map[string]string{
67
			"authorization": "Bearer " + token,
68
		}, nil
69
	}
70
	return t.opts.TokenManager.GetMetadata(t.forCA, t.opts.XdsAuthProvider, token)
71
}
72

73
// Allow the token provider to be used regardless of transport security; callers can determine whether
74
// this is safe themselves.
75
func (t *TokenProvider) RequireTransportSecurity() bool {
76
	return false
77
}
78

79
// GetToken fetches a token to attach to a request. Returning "", nil will cause no header to be
80
// added; while a non-nil error will block the request If the token selected is not found, no error
81
// will be returned, causing no authorization header to be set. This ensures that even if the JWT
82
// token is missing (for example, on a VM that has rebooted, causing the token to be removed from
83
// volatile memory), we can still proceed and allow other authentication methods to potentially
84
// handle the request, such as mTLS.
85
func (t *TokenProvider) GetToken() (string, error) {
86
	if t.opts.CredFetcher == nil {
87
		return "", nil
88
	}
89
	token, err := t.opts.CredFetcher.GetPlatformCredential()
90
	if err != nil {
91
		return "", fmt.Errorf("fetch platform credential: %v", err)
92
	}
93

94
	// Regardless of where the token came from, we (optionally) can exchange the token for a different
95
	if t.forCA {
96
		return t.exchangeCAToken(token)
97
	}
98
	return t.exchangeXDSToken(token)
99
}
100

101
// exchangeCAToken exchanges the provided token using TokenExchanger, if configured. If not, the
102
// original token is returned.
103
func (t *TokenProvider) exchangeCAToken(token string) (string, error) {
104
	if t.opts.TokenExchanger == nil {
105
		return token, nil
106
	}
107
	return t.opts.TokenExchanger.ExchangeToken(token)
108
}
109

110
func (t *TokenProvider) exchangeXDSToken(token string) (string, error) {
111
	if t.opts.XdsAuthProvider != google.GCPAuthProvider {
112
		return token, nil
113
	}
114

115
	// For XDS flow, the token exchange is different from that of the CA flow.
116
	if t.opts.TokenManager == nil {
117
		return "", fmt.Errorf("XDS token exchange is enabled but token manager is nil")
118
	}
119
	if token == "" {
120
		return "", fmt.Errorf("the token for XDS token exchange is empty")
121
	}
122
	params := security.StsRequestParameters{
123
		Scope:            stsclient.Scope,
124
		GrantType:        server.TokenExchangeGrantType,
125
		SubjectToken:     token,
126
		SubjectTokenType: server.SubjectTokenType,
127
	}
128
	body, err := t.opts.TokenManager.GenerateToken(params)
129
	if err != nil {
130
		return "", fmt.Errorf("token manager failed to generate access token: %v", err)
131
	}
132
	respData := &stsservice.StsResponseParameters{}
133
	if err := json.Unmarshal(body, respData); err != nil {
134
		return "", fmt.Errorf("failed to unmarshal access token response data: %v", err)
135
	}
136
	return respData.AccessToken, nil
137
}
138

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

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

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

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