forked from kubernetes/kubernetes
-
Notifications
You must be signed in to change notification settings - Fork 0
/
gke_signer.go
90 lines (72 loc) · 2.72 KB
/
gke_signer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package app
import (
"fmt"
"time"
"github.com/golang/glog"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/util/webhook"
"k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/api"
_ "k8s.io/kubernetes/pkg/apis/certificates/install"
certificates "k8s.io/kubernetes/pkg/apis/certificates/v1beta1"
)
var (
groupVersions = []schema.GroupVersion{certificates.SchemeGroupVersion}
)
// GKESigner uses external calls to GKE in order to sign certificate signing
// requests.
type GKESigner struct {
webhook *webhook.GenericWebhook
kubeConfigFile string
retryBackoff time.Duration
}
// NewGKESigner will create a new instance of a GKESigner.
func NewGKESigner(kubeConfigFile string, retryBackoff time.Duration) (*GKESigner, error) {
webhook, err := webhook.NewGenericWebhook(api.Registry, api.Codecs, kubeConfigFile, groupVersions, retryBackoff)
if err != nil {
return nil, err
}
return &GKESigner{
webhook: webhook,
kubeConfigFile: kubeConfigFile,
retryBackoff: retryBackoff,
}, nil
}
// Sign will make an external call to GKE order to sign the given
// *certificates.CertificateSigningRequest, using the GKESigner's
// kubeConfigFile.
func (s *GKESigner) Sign(csr *certificates.CertificateSigningRequest) (*certificates.CertificateSigningRequest, error) {
result := s.webhook.WithExponentialBackoff(func() rest.Result {
return s.webhook.RestClient.Post().Body(csr).Do()
})
if err := result.Error(); err != nil {
return nil, s.webhookError(csr, err)
}
var statusCode int
if result.StatusCode(&statusCode); statusCode < 200 || statusCode >= 300 {
return nil, s.webhookError(csr, fmt.Errorf("received unsuccessful response code from webhook: %d", statusCode))
}
result_csr := &certificates.CertificateSigningRequest{}
if err := result.Into(result_csr); err != nil {
return nil, s.webhookError(result_csr, err)
}
// Keep the original CSR intact, and only update fields we expect to change.
csr.Status.Certificate = result_csr.Status.Certificate
return csr, nil
}
func (s *GKESigner) webhookError(csr *certificates.CertificateSigningRequest, err error) error {
glog.V(2).Infof("error contacting webhook backend: %s", err)
return err
}