Skip to content

Commit 112a490

Browse files
authored
introduce examples/dyplomat (#336)
* introduce examples/dyplomat Signed-off-by: Ashley Kasim <[email protected]> * build dyplomat in CI, specify terraform version required Signed-off-by: Ashley Kasim <[email protected]>
1 parent 462a218 commit 112a490

24 files changed

+1790
-0
lines changed

.circleci/config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ jobs:
99
- run: make create_version
1010
- run: make check_version_dirty
1111
- run: make build
12+
- run: make examples
1213
- run: make test
1314
- run: make integration
1415
- run:

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ create_version:
3232
check_version_dirty:
3333
./scripts/check_version_dirty.sh
3434

35+
.PHONY: examples
36+
examples:
37+
@pushd examples/dyplomat && go build ./... && popd
38+
3539
#-----------------
3640
#-- integration
3741
#-----------------

examples/dyplomat/Dockerfile

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
FROM golang:1.14
2+
3+
WORKDIR /go/src/dyplomat
4+
COPY . /go/src/dyplomat
5+
6+
RUN go install -v ./...
7+
CMD ["dyplomat"]

examples/dyplomat/auth.go

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"sync"
7+
"time"
8+
9+
utilnet "k8s.io/apimachinery/pkg/util/net"
10+
heptiotoken "sigs.k8s.io/aws-iam-authenticator/pkg/token"
11+
)
12+
13+
// TokenKind defines the token type used for remote authentication to your cluster(s).
14+
// An example NullToken and the implementation for HeptioToken (AWS) are provided.
15+
type TokenKind int
16+
17+
const (
18+
HeptioTokenKind TokenKind = iota
19+
NullTokenKind
20+
)
21+
22+
// NullTokenProvider always returns a nil token
23+
type NullTokenProvider struct{}
24+
25+
func (t *NullTokenProvider) Kind() TokenKind {
26+
return NullTokenKind
27+
}
28+
29+
// AuthToken contains an auth token and its expiry time
30+
type AuthToken struct {
31+
Token string
32+
expires time.Time
33+
}
34+
35+
// Expired return whether or not the token has past its expiry time
36+
func (t *AuthToken) Expired() bool {
37+
return time.Now().After(t.expires)
38+
}
39+
40+
type Provider interface {
41+
// Token provides a time limited token
42+
Token() (*AuthToken, error)
43+
Kind() TokenKind
44+
}
45+
46+
// Generator interface defines the ability to grab token providers based on the cluster name
47+
type Generator interface {
48+
ProviderForCluster(cluster string) (Provider, error)
49+
}
50+
51+
// GeneratorProvider is a token provider which mints tokens as well
52+
type GeneratorProvider interface {
53+
Provider
54+
Generator
55+
}
56+
57+
type heptioTokenProvider struct {
58+
lastToken *AuthToken
59+
clusterName string
60+
lock sync.Mutex
61+
}
62+
63+
func (t *heptioTokenProvider) refresh() error {
64+
t.lock.Lock()
65+
defer t.lock.Unlock()
66+
67+
gen, err := heptiotoken.NewGenerator(false, false)
68+
if err != nil {
69+
fmt.Printf("heptio authenticator error %v", err)
70+
return err
71+
}
72+
rawToken, err := gen.Get(t.clusterName)
73+
74+
if err != nil {
75+
fmt.Printf("token data invalid %v", err)
76+
return err
77+
}
78+
79+
token := AuthToken{
80+
Token: rawToken.Token,
81+
expires: rawToken.Expiration,
82+
}
83+
84+
t.lastToken = &token
85+
return nil
86+
}
87+
88+
// Token returns a heptio token, refreshing it if need be
89+
func (t *heptioTokenProvider) Token() (*AuthToken, error) {
90+
if t.lastToken != nil {
91+
if time.Now().After(t.lastToken.expires) {
92+
err := t.refresh()
93+
if err != nil {
94+
return nil, err
95+
}
96+
}
97+
} else {
98+
err := t.refresh()
99+
if err != nil {
100+
return nil, err
101+
}
102+
}
103+
104+
return t.lastToken, nil
105+
}
106+
107+
func (t *heptioTokenProvider) Kind() TokenKind {
108+
return HeptioTokenKind
109+
}
110+
111+
// NewHeptioProvider returns an initialized heptio token provider
112+
func NewHeptioProvider(clusterName string) Provider {
113+
return &heptioTokenProvider{
114+
clusterName: clusterName,
115+
}
116+
}
117+
118+
type heptioGenerator struct {
119+
clusters sync.Map
120+
}
121+
122+
func (h *heptioGenerator) ProviderForCluster(cluster string) (Provider, error) {
123+
provider := NewHeptioProvider(cluster)
124+
providerFromMap, _ := h.clusters.LoadOrStore(cluster, provider)
125+
return providerFromMap.(*heptioTokenProvider), nil
126+
}
127+
128+
func NewHeptioGenetor() Generator {
129+
return &heptioGenerator{}
130+
}
131+
132+
type requestCanceler interface {
133+
CancelRequest(*http.Request)
134+
}
135+
136+
type TokenRoundtripper struct {
137+
RoundTripper http.RoundTripper
138+
TokenProvider Provider
139+
}
140+
141+
func (rt *TokenRoundtripper) RoundTrip(req *http.Request) (*http.Response, error) {
142+
if len(req.Header.Get("Authorization")) != 0 {
143+
return rt.RoundTripper.RoundTrip(req)
144+
}
145+
146+
req = utilnet.CloneRequest(req)
147+
token, err := rt.TokenProvider.Token()
148+
if err != nil {
149+
return nil, err
150+
151+
}
152+
153+
req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token.Token))
154+
return rt.RoundTripper.RoundTrip(req)
155+
}
156+
157+
func (rt *TokenRoundtripper) CancelRequest(req *http.Request) {
158+
if canceler, ok := rt.RoundTripper.(requestCanceler); ok {
159+
canceler.CancelRequest(req)
160+
}
161+
}

examples/dyplomat/bootstrap.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package main
2+
3+
import (
4+
"encoding/base64"
5+
"io/ioutil"
6+
"net/http"
7+
"strings"
8+
"time"
9+
10+
yaml "gopkg.in/yaml.v2"
11+
12+
"k8s.io/client-go/kubernetes"
13+
"k8s.io/client-go/rest"
14+
)
15+
16+
type BootstrapConfig struct {
17+
Name string
18+
Server string
19+
CA string // CA is expected to be base64 encoded PEM file
20+
}
21+
22+
var bootstrapConfigs []BootstrapConfig
23+
24+
func CreateBootstrapClients() ([]kubernetes.Interface, error) {
25+
var bootstrapClients []kubernetes.Interface
26+
27+
bootstrapYaml, err := ioutil.ReadFile("./bootstrap.yaml")
28+
if err != nil {
29+
panic(err)
30+
}
31+
32+
err = yaml.Unmarshal(bootstrapYaml, &bootstrapConfigs)
33+
if err != nil {
34+
panic(err)
35+
}
36+
37+
for _, cluster := range bootstrapConfigs {
38+
// CA is base64 encoded, so we decode
39+
caReader := base64.NewDecoder(base64.StdEncoding, strings.NewReader(cluster.CA))
40+
caBytes, _ := ioutil.ReadAll(caReader)
41+
42+
var restConfig *rest.Config
43+
restConfig = &rest.Config{
44+
Host: cluster.Server,
45+
TLSClientConfig: rest.TLSClientConfig{
46+
CAData: caBytes,
47+
},
48+
}
49+
50+
previousWrappedTransport := restConfig.WrapTransport
51+
restConfig.WrapTransport = func(rt http.RoundTripper) http.RoundTripper {
52+
if previousWrappedTransport != nil {
53+
rt = previousWrappedTransport(rt)
54+
}
55+
return &TokenRoundtripper{
56+
TokenProvider: NewHeptioProvider(cluster.Name),
57+
RoundTripper: rt,
58+
}
59+
}
60+
61+
restConfig.Timeout = time.Second * 5
62+
63+
client, err := kubernetes.NewForConfig(restConfig)
64+
if err != nil {
65+
return nil, err
66+
}
67+
bootstrapClients = append(bootstrapClients, client)
68+
}
69+
return bootstrapClients, nil
70+
}

examples/dyplomat/bootstrap.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# bootstrapYaml is a simple cluster discovery mechanism to register the Kubernetes clusters we will be extending the mesh to.
2+
- name: demo1-eks
3+
server: DEMO1_API_SERVER_URL
4+
ca: DEMO1_BASE_64_ENCODED_CA
5+
- name: demo2-eks
6+
server: DEMO2_API_SERVER_URL
7+
ca: DEMO2_BASE_64_ENCODED_CA

examples/dyplomat/go.mod

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module kubecon-demo/dyplomat
2+
3+
go 1.14
4+
5+
require (
6+
github.com/envoyproxy/go-control-plane v0.9.6
7+
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect
8+
google.golang.org/grpc v1.30.0
9+
gopkg.in/yaml.v2 v2.2.8
10+
k8s.io/api v0.18.6
11+
k8s.io/apimachinery v0.18.6
12+
k8s.io/client-go v11.0.0+incompatible
13+
sigs.k8s.io/aws-iam-authenticator v0.5.1
14+
)
15+
16+
replace (
17+
k8s.io/api => k8s.io/api v0.18.6
18+
k8s.io/apimachinery => k8s.io/apimachinery v0.18.6
19+
k8s.io/client-go => k8s.io/client-go v0.18.6
20+
)

0 commit comments

Comments
 (0)