istio

Форк
0
142 строки · 4.5 Кб
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
	"fmt"
20
	"time"
21

22
	privateca "cloud.google.com/go/security/privateca/apiv1"
23
	privatecapb "cloud.google.com/go/security/privateca/apiv1/privatecapb"
24
	"google.golang.org/api/option"
25
	"google.golang.org/protobuf/types/known/durationpb"
26
	"k8s.io/apimachinery/pkg/util/rand"
27

28
	"istio.io/istio/pkg/log"
29
	"istio.io/istio/pkg/security"
30
	"istio.io/istio/pkg/util/sets"
31
)
32

33
var googleCASClientLog = log.RegisterScope("googlecas", "Google CAS client debugging")
34

35
// GoogleCASClient: Agent side plugin for Google CAS
36
type GoogleCASClient struct {
37
	caSigner string
38
	caClient *privateca.CertificateAuthorityClient
39
}
40

41
// NewGoogleCASClient create a CA client for Google CAS.
42
func NewGoogleCASClient(capool string, options ...option.ClientOption) (security.Client, error) {
43
	caClient := &GoogleCASClient{caSigner: capool}
44
	ctx := context.Background()
45
	var err error
46

47
	caClient.caClient, err = privateca.NewCertificateAuthorityClient(ctx, options...)
48
	if err != nil {
49
		googleCASClientLog.Errorf("unable to initialize google cas caclient: %v", err)
50
		return nil, err
51
	}
52
	googleCASClientLog.Debugf("Intitialized Google CAS plugin with endpoint: %v", capool)
53
	return caClient, nil
54
}
55

56
func (r *GoogleCASClient) createCertReq(name string, csrPEM []byte, lifetime time.Duration) *privatecapb.CreateCertificateRequest {
57
	isCA := false
58

59
	// We use Certificate_Config option to ensure that we only request a certificate with CAS supported extensions/usages.
60
	// CAS uses the PEM encoded CSR only for its public key and infers the certificate SAN (identity) of the workload through SPIFFE identity reflection
61
	creq := &privatecapb.CreateCertificateRequest{
62
		Parent:        r.caSigner,
63
		CertificateId: name,
64
		Certificate: &privatecapb.Certificate{
65
			Lifetime: durationpb.New(lifetime),
66
			CertificateConfig: &privatecapb.Certificate_Config{
67
				Config: &privatecapb.CertificateConfig{
68
					SubjectConfig: &privatecapb.CertificateConfig_SubjectConfig{
69
						Subject: &privatecapb.Subject{},
70
					},
71
					X509Config: &privatecapb.X509Parameters{
72
						KeyUsage: &privatecapb.KeyUsage{
73
							BaseKeyUsage: &privatecapb.KeyUsage_KeyUsageOptions{
74
								DigitalSignature: true,
75
								KeyEncipherment:  true,
76
							},
77
							ExtendedKeyUsage: &privatecapb.KeyUsage_ExtendedKeyUsageOptions{
78
								ServerAuth: true,
79
								ClientAuth: true,
80
							},
81
						},
82
						CaOptions: &privatecapb.X509Parameters_CaOptions{
83
							IsCa: &isCA,
84
						},
85
					},
86
					PublicKey: &privatecapb.PublicKey{
87
						Format: privatecapb.PublicKey_PEM,
88
						Key:    csrPEM,
89
					},
90
				},
91
			},
92
			SubjectMode: privatecapb.SubjectRequestMode_REFLECTED_SPIFFE,
93
		},
94
	}
95
	return creq
96
}
97

98
// CSR Sign calls Google CAS to sign a CSR.
99
func (r *GoogleCASClient) CSRSign(csrPEM []byte, certValidTTLInSec int64) ([]string, error) {
100
	certChain := []string{}
101

102
	name := fmt.Sprintf("csr-workload-%s", rand.String(8))
103
	creq := r.createCertReq(name, csrPEM, time.Duration(certValidTTLInSec)*time.Second)
104

105
	ctx := context.Background()
106

107
	cresp, err := r.caClient.CreateCertificate(ctx, creq)
108
	if err != nil {
109
		googleCASClientLog.Errorf("unable to create certificate: %v", err)
110
		return []string{}, err
111
	}
112
	certChain = append(certChain, cresp.GetPemCertificate())
113
	certChain = append(certChain, cresp.GetPemCertificateChain()...)
114
	return certChain, nil
115
}
116

117
// GetRootCertBundle:  Get CA certs of the pool from Google CAS API endpoint
118
func (r *GoogleCASClient) GetRootCertBundle() ([]string, error) {
119
	rootCertSet := sets.New[string]()
120

121
	ctx := context.Background()
122

123
	req := &privatecapb.FetchCaCertsRequest{
124
		CaPool: r.caSigner,
125
	}
126
	resp, err := r.caClient.FetchCaCerts(ctx, req)
127
	if err != nil {
128
		googleCASClientLog.Errorf("error when getting root-certs from CAS pool: %v", err)
129
		return nil, err
130
	}
131
	for _, certChain := range resp.CaCerts {
132
		certs := certChain.Certificates
133
		rootCert := certs[len(certs)-1]
134
		rootCertSet.Insert(rootCert)
135
	}
136

137
	return sets.SortedList(rootCertSet), nil
138
}
139

140
func (r *GoogleCASClient) Close() {
141
	_ = r.caClient.Close()
142
}
143

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

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

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

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