Skip to content

Commit 166faaf

Browse files
committed
Adding support for agent authenticate server by using kubeapi-server ca
certificate.
1 parent 2260a7e commit 166faaf

File tree

12 files changed

+391
-81
lines changed

12 files changed

+391
-81
lines changed

Makefile

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ STAGING_REGISTRY := gcr.io/k8s-staging-kas-network-proxy
2020

2121
SERVER_IMAGE_NAME ?= proxy-server
2222
AGENT_IMAGE_NAME ?= proxy-agent
23+
TEST_CLIENT_IMAGE_NAME ?= proxy-test-client
2324

2425
SERVER_FULL_IMAGE ?= $(REGISTRY)/$(SERVER_IMAGE_NAME)
2526
AGENT_FULL_IMAGE ?= $(REGISTRY)/$(AGENT_IMAGE_NAME)
27+
TEST_CLIENT_FULL_IMAGE ?= $(REGISTRY)/$(TEST_CLIENT_IMAGE_NAME)
2628

2729
TAG ?= $(shell git rev-parse HEAD)
2830

@@ -131,10 +133,10 @@ certs: easy-rsa-master cfssl cfssljson
131133
## --------------------------------------
132134

133135
.PHONY: docker-build
134-
docker-build: docker-build/proxy-agent docker-build/proxy-server
136+
docker-build: docker-build/proxy-agent docker-build/proxy-server docker-build/proxy-test-client
135137

136138
.PHONY: docker-push
137-
docker-push: docker-push/proxy-agent docker-push/proxy-server
139+
docker-push: docker-push/proxy-agent docker-push/proxy-server docker-push/proxy-test-client
138140

139141
.PHONY: docker-build/proxy-agent
140142
docker-build/proxy-agent: cmd/agent/main.go proto/agent/agent.pb.go
@@ -158,17 +160,29 @@ docker-push/proxy-server: docker-build/proxy-server
158160
@[ "${DOCKER_CMD}" ] || ( echo "DOCKER_CMD is not set"; exit 1 )
159161
${DOCKER_CMD} push ${SERVER_FULL_IMAGE}-$(ARCH):${TAG}
160162

163+
.PHONY: docker-build/proxy-test-client
164+
docker-build/proxy-test-client: cmd/client/main.go proto/agent/agent.pb.go proto/proxy.pb.go
165+
@[ "${TAG}" ] || ( echo "TAG is not set"; exit 1 )
166+
echo "Building proxy-test-client for ${ARCH}"
167+
${DOCKER_CMD} build . --build-arg ARCH=$(ARCH) -f artifacts/images/client-build.Dockerfile -t ${TEST_CLIENT_FULL_IMAGE}-$(ARCH):${TAG}
168+
169+
.PHONY: docker-push/proxy-test-client
170+
docker-push/proxy-test-client: docker-build/proxy-test-client
171+
@[ "${DOCKER_CMD}" ] || ( echo "DOCKER_CMD is not set"; exit 1 )
172+
${DOCKER_CMD} push ${TEST_CLIENT_FULL_IMAGE}-$(ARCH):${TAG}
173+
161174
## --------------------------------------
162175
## Docker — All ARCH
163176
## --------------------------------------
164177

165178
.PHONY: docker-build-all
166-
docker-build-all: $(addprefix docker-build/proxy-agent-,$(ALL_ARCH)) $(addprefix docker-build/proxy-server-,$(ALL_ARCH))
179+
docker-build-all: $(addprefix docker-build/proxy-agent-,$(ALL_ARCH)) $(addprefix docker-build/proxy-server-,$(ALL_ARCH)) $(addprefix docker-build/proxy-test-client-,$(ALL_ARCH))
167180

168181
.PHONY: docker-push-all
169-
docker-push-all: $(addprefix docker-push/proxy-agent-,$(ALL_ARCH)) $(addprefix docker-push/proxy-server-,$(ALL_ARCH))
182+
docker-push-all: $(addprefix docker-push/proxy-agent-,$(ALL_ARCH)) $(addprefix docker-push/proxy-server-,$(ALL_ARCH)) $(addprefix docker-push/proxy-test-client-,$(ALL_ARCH))
170183
$(MAKE) docker-push-manifest/proxy-agent
171184
$(MAKE) docker-push-manifest/proxy-server
185+
$(MAKE) docker-push-manifest/test-client
172186

173187
docker-build/proxy-agent-%:
174188
$(MAKE) ARCH=$* docker-build/proxy-agent
@@ -182,6 +196,13 @@ docker-build/proxy-server-%:
182196
docker-push/proxy-server-%:
183197
$(MAKE) ARCH=$* docker-push/proxy-server
184198

199+
docker-build/proxy-test-client-%:
200+
$(MAKE) ARCH=$* docker-build/proxy-test-client
201+
202+
docker-push/proxy-test-client-%:
203+
$(MAKE) ARCH=$* docker-push/proxy-test-client
204+
205+
185206
.PHONY: docker-push-manifest/proxy-agent
186207
docker-push-manifest/proxy-agent: ## Push the fat manifest docker image.
187208
## Minimum docker version 18.06.0 is required for creating and pushing manifest images.
@@ -196,6 +217,13 @@ docker-push-manifest/proxy-server: ## Push the fat manifest docker image.
196217
@for arch in $(ALL_ARCH); do ${DOCKER_CMD} manifest annotate --arch $${arch} ${SERVER_FULL_IMAGE}:${TAG} ${SERVER_FULL_IMAGE}-$${arch}:${TAG}; done
197218
${DOCKER_CMD} manifest push --purge $(SERVER_FULL_IMAGE):$(TAG)
198219

220+
.PHONY: docker-push-manifest/proxy-test-client
221+
docker-push-manifest/proxy-test-client: ## Push the fat manifest docker image.
222+
## Minimum docker version 18.06.0 is required for creating and pushing manifest images.
223+
${DOCKER_CMD} manifest create --amend $(TEST_CLIENT_FULL_IMAGE):$(TAG) $(shell echo $(ALL_ARCH) | sed -e "s~[^ ]*~$(TEST_CLIENT_FULL_IMAGE)\-&:$(TAG)~g")
224+
@for arch in $(ALL_ARCH); do ${DOCKER_CMD} manifest annotate --arch $${arch} ${TEST_CLIENT_FULL_IMAGE}:${TAG} ${TEST_CLIENT_FULL_IMAGE}-$${arch}:${TAG}; done
225+
${DOCKER_CMD} manifest push --purge $(TEST_CLIENT_FULL_IMAGE):$(TAG)
226+
199227
## --------------------------------------
200228
## Release
201229
## --------------------------------------
@@ -208,6 +236,7 @@ release-staging: ## Builds and push container images to the staging bucket.
208236
release-alias-tag: # Adds the tag to the last build tag. BASE_REF comes from the cloudbuild.yaml
209237
gcloud container images add-tag $(AGENT_FULL_IMAGE):$(TAG) $(AGENT_FULL_IMAGE):$(BASE_REF)
210238
gcloud container images add-tag $(SERVER_FULL_IMAGE):$(TAG) $(SERVER_FULL_IMAGE):$(BASE_REF)
239+
gcloud container images add-tag $(TEST_CLIENT_FULL_IMAGE):$(TAG) $(TEST_CLIENT_FULL_IMAGE):$(BASE_REF)
211240

212241
## --------------------------------------
213242
## Cleanup / Verification

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,9 @@ python -m SimpleHTTPServer
108108
curl -v -p --proxy-key certs/master/private/proxy-client.key --proxy-cert certs/master/issued/proxy-client.crt --proxy-cacert certs/master/issued/ca.crt --proxy-cert-type PEM -x https://127.0.0.1:8090 http://localhost:8000```
109109
```
110110

111+
### Running on kubernetes
112+
See following [README.md](examples/kubernetes/README.md)
113+
111114
## Troubleshoot
112115

113116
### Undefined ProtoPackageIsVersion3
@@ -118,4 +121,3 @@ protoc-gen-go binary has to be built from the vendored version:
118121
go install ./vendor/github.com/golang/protobuf/protoc-gen-go
119122
make gen
120123
```
121-
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Build the client binary
2+
FROM golang:1.12.1 as builder
3+
4+
# Copy in the go src
5+
WORKDIR /go/src/sigs.k8s.io/apiserver-network-proxy
6+
COPY pkg/ pkg/
7+
COPY cmd/ cmd/
8+
COPY proto/ proto/
9+
COPY vendor/ vendor/
10+
11+
# Build
12+
ARG ARCH
13+
RUN CGO_ENABLED=0 GOOS=linux GOARCH=${ARCH} go build -a -ldflags '-extldflags "-static"' -o proxy-test-client sigs.k8s.io/apiserver-network-proxy/cmd/client
14+
15+
# Copy the loader into a thin image
16+
FROM scratch
17+
WORKDIR /
18+
COPY --from=builder /go/src/sigs.k8s.io/apiserver-network-proxy/proxy-test-client .
19+
ENTRYPOINT ["/proxy-test-client"]

cmd/agent/main.go

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,8 @@ package main
1818

1919
import (
2020
"crypto/tls"
21-
"crypto/x509"
2221
"flag"
2322
"fmt"
24-
"io/ioutil"
2523
"net/http"
2624
"os"
2725

@@ -158,26 +156,12 @@ func (a *Agent) run(o *GrpcProxyAgentOptions) error {
158156
}
159157

160158
func (a *Agent) runProxyConnection(o *GrpcProxyAgentOptions) error {
161-
agentCert, err := tls.LoadX509KeyPair(o.agentCert, o.agentKey)
162-
if err != nil {
163-
return fmt.Errorf("failed to load X509 key pair %s and %s: %v", o.agentCert, o.agentKey, err)
164-
}
165-
certPool := x509.NewCertPool()
166-
caCert, err := ioutil.ReadFile(o.caCert)
167-
if err != nil {
168-
return fmt.Errorf("failed to read agent CA cert %s: %v", o.caCert, err)
169-
}
170-
ok := certPool.AppendCertsFromPEM(caCert)
171-
if !ok {
172-
return fmt.Errorf("failed to append CA cert to the cert pool")
159+
var tlsConfig *tls.Config
160+
var err error
161+
if tlsConfig, err = util.GetClientTLSConfig(o.caCert, o.agentCert, o.agentKey, o.proxyServerHost); err != nil {
162+
return err
173163
}
174-
175-
transportCreds := credentials.NewTLS(&tls.Config{
176-
ServerName: o.proxyServerHost,
177-
Certificates: []tls.Certificate{agentCert},
178-
RootCAs: certPool,
179-
})
180-
dialOption := grpc.WithTransportCredentials(transportCreds)
164+
dialOption := grpc.WithTransportCredentials(credentials.NewTLS(tlsConfig))
181165
client, err := agentclient.NewAgentClient(fmt.Sprintf("%s:%d", o.proxyServerHost, o.proxyServerPort), dialOption)
182166
if err != nil {
183167
return err

cmd/client/main.go

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"bufio"
2121
"context"
2222
"crypto/tls"
23-
"crypto/x509"
2423
"flag"
2524
"fmt"
2625
"io/ioutil"
@@ -57,6 +56,7 @@ func main() {
5756
klog.Flush()
5857
os.Exit(1)
5958
}
59+
klog.Flush()
6060
}
6161

6262
type GrpcProxyClientOptions struct {
@@ -84,7 +84,7 @@ func (o *GrpcProxyClientOptions) Flags() *pflag.FlagSet {
8484
flags.IntVar(&o.requestPort, "request-port", o.requestPort, "The port the request server is listening on.")
8585
flags.StringVar(&o.proxyHost, "proxy-host", o.proxyHost, "The host of the proxy server.")
8686
flags.IntVar(&o.proxyPort, "proxy-port", o.proxyPort, "The port the proxy server is listening on.")
87-
flags.StringVar(&o.proxyUdsName, "proxy-uds", o.proxyHost, "The UDS name to connect to.")
87+
flags.StringVar(&o.proxyUdsName, "proxy-uds", o.proxyUdsName, "The UDS name to connect to.")
8888
flags.StringVar(&o.mode, "mode", o.mode, "Mode can be either 'grpc' or 'http-connect'.")
8989

9090
return flags
@@ -142,6 +142,9 @@ func (o *GrpcProxyClientOptions) Validate() error {
142142
return fmt.Errorf("please do not try to use reserved port %d for the proxy server port", o.proxyPort)
143143
}
144144
if o.proxyUdsName != "" {
145+
if o.proxyHost != "" {
146+
return fmt.Errorf("please do set proxy host when using UDS")
147+
}
145148
if o.proxyPort != 0 {
146149
return fmt.Errorf("please do set proxy server port to 0 not %d when using UDS", o.proxyPort)
147150
}
@@ -305,25 +308,12 @@ func (c *Client) getUDSDialer(o *GrpcProxyClientOptions) (func(ctx context.Conte
305308
}
306309

307310
func (c *Client) getMTLSDialer(o *GrpcProxyClientOptions) (func(ctx context.Context, network, addr string) (net.Conn, error), error) {
308-
clientCert, err := tls.LoadX509KeyPair(o.clientCert, o.clientKey)
309-
if err != nil {
310-
return nil, fmt.Errorf("failed to read key pair %s & %s, got %v", o.clientCert, o.clientKey, err)
311-
}
312-
certPool := x509.NewCertPool()
313-
caCert, err := ioutil.ReadFile(o.caCert)
311+
var tlsConfig *tls.Config
312+
var err error
313+
tlsConfig, err = util.GetClientTLSConfig(o.caCert, o.clientCert, o.clientKey, o.proxyHost)
314314
if err != nil {
315-
return nil, fmt.Errorf("failed to read cert file %s, got %v", o.caCert, err)
315+
return nil, err
316316
}
317-
ok := certPool.AppendCertsFromPEM(caCert)
318-
if !ok {
319-
return nil, fmt.Errorf("failed to append CA cert to the cert pool")
320-
}
321-
322-
transportCreds := credentials.NewTLS(&tls.Config{
323-
ServerName: "127.0.0.1",
324-
Certificates: []tls.Certificate{clientCert},
325-
RootCAs: certPool,
326-
})
327317

328318
var proxyConn net.Conn
329319

@@ -339,6 +329,7 @@ func (c *Client) getMTLSDialer(o *GrpcProxyClientOptions) (func(ctx context.Cont
339329

340330
switch o.mode {
341331
case "grpc":
332+
transportCreds := credentials.NewTLS(tlsConfig)
342333
dialOption := grpc.WithTransportCredentials(transportCreds)
343334
serverAddress := fmt.Sprintf("%s:%d", o.proxyHost, o.proxyPort)
344335
tunnel, err := client.CreateGrpcTunnel(serverAddress, dialOption)
@@ -355,13 +346,7 @@ func (c *Client) getMTLSDialer(o *GrpcProxyClientOptions) (func(ctx context.Cont
355346
proxyAddress := fmt.Sprintf("%s:%d", o.proxyHost, o.proxyPort)
356347
requestAddress := fmt.Sprintf("%s:%d", o.requestHost, o.requestPort)
357348

358-
proxyConn, err = tls.Dial("tcp", proxyAddress,
359-
&tls.Config{
360-
ServerName: o.proxyHost,
361-
Certificates: []tls.Certificate{clientCert},
362-
RootCAs: certPool,
363-
},
364-
)
349+
proxyConn, err = tls.Dial("tcp", proxyAddress, tlsConfig)
365350
if err != nil {
366351
return nil, fmt.Errorf("dialing proxy %q failed: %v", proxyAddress, err)
367352
}

cmd/proxy/main.go

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ import (
3838
"sigs.k8s.io/apiserver-network-proxy/pkg/agent/agentserver"
3939
"sigs.k8s.io/apiserver-network-proxy/pkg/util"
4040
"sigs.k8s.io/apiserver-network-proxy/proto/agent"
41-
4241
)
4342

4443
func main() {
@@ -329,28 +328,43 @@ func (p *Proxy) runUDSMasterServer(ctx context.Context, o *ProxyRunOptions, serv
329328
return stop, nil
330329
}
331330

332-
func (p *Proxy) runMTLSMasterServer(ctx context.Context, o *ProxyRunOptions, server *agentserver.ProxyServer) (StopFunc, error) {
333-
var stop StopFunc
334-
335-
proxyCert, err := tls.LoadX509KeyPair(o.serverCert, o.serverKey)
331+
func (p *Proxy) getTLSConfig(caFile, certFile, keyFile string) (*tls.Config, error) {
332+
cert, err := tls.LoadX509KeyPair(certFile, keyFile)
336333
if err != nil {
337-
return nil, fmt.Errorf("failed to load X509 key pair %s and %s: %v", o.serverCert, o.serverKey, err)
334+
return nil, fmt.Errorf("failed to load X509 key pair %s and %s: %v", certFile, keyFile, err)
338335
}
336+
337+
if caFile == "" {
338+
return &tls.Config{Certificates: []tls.Certificate{cert}}, nil
339+
}
340+
339341
certPool := x509.NewCertPool()
340-
caCert, err := ioutil.ReadFile(o.serverCaCert)
342+
caCert, err := ioutil.ReadFile(caFile)
341343
if err != nil {
342-
return nil, fmt.Errorf("failed to read server CA cert %s: %v", o.serverCaCert, err)
344+
return nil, fmt.Errorf("failed to read cluster CA cert %s: %v", caFile, err)
343345
}
344346
ok := certPool.AppendCertsFromPEM(caCert)
345347
if !ok {
346-
return nil, fmt.Errorf("failed to append master CA cert to the cert pool")
348+
return nil, fmt.Errorf("failed to append cluster CA cert to the cert pool")
347349
}
348-
349350
tlsConfig := &tls.Config{
350351
ClientAuth: tls.RequireAndVerifyClientCert,
351-
Certificates: []tls.Certificate{proxyCert},
352+
Certificates: []tls.Certificate{cert},
352353
ClientCAs: certPool,
353354
}
355+
356+
return tlsConfig, nil
357+
}
358+
359+
func (p *Proxy) runMTLSMasterServer(ctx context.Context, o *ProxyRunOptions, server *agentserver.ProxyServer) (StopFunc, error) {
360+
var stop StopFunc
361+
362+
var tlsConfig *tls.Config
363+
var err error
364+
if tlsConfig, err = p.getTLSConfig(o.serverCaCert, o.serverCert, o.serverKey); err != nil {
365+
return nil, err
366+
}
367+
354368
addr := fmt.Sprintf(":%d", o.serverPort)
355369

356370
if o.mode == "grpc" {
@@ -386,26 +400,13 @@ func (p *Proxy) runMTLSMasterServer(ctx context.Context, o *ProxyRunOptions, ser
386400
}
387401

388402
func (p *Proxy) runAgentServer(o *ProxyRunOptions, server *agentserver.ProxyServer) error {
389-
clusterCert, err := tls.LoadX509KeyPair(o.clusterCert, o.clusterKey)
390-
if err != nil {
391-
return fmt.Errorf("failed to load X509 key pair %s and %s: %v", o.clusterCert, o.clusterKey, err)
392-
}
393-
certPool := x509.NewCertPool()
394-
caCert, err := ioutil.ReadFile(o.clusterCaCert)
395-
if err != nil {
396-
return fmt.Errorf("failed to read cluster CA cert %s: %v", o.clusterCaCert, err)
397-
}
398-
ok := certPool.AppendCertsFromPEM(caCert)
399-
if !ok {
400-
return fmt.Errorf("failed to append cluster CA cert to the cert pool")
403+
var tlsConfig *tls.Config
404+
var err error
405+
if tlsConfig, err = p.getTLSConfig(o.clusterCaCert, o.clusterCert, o.clusterKey); err != nil {
406+
return err
401407
}
402-
tlsConfig := &tls.Config{
403-
ClientAuth: tls.RequireAndVerifyClientCert,
404-
Certificates: []tls.Certificate{clusterCert},
405-
ClientCAs: certPool,
406-
}
407-
addr := fmt.Sprintf(":%d", o.agentPort)
408408

409+
addr := fmt.Sprintf(":%d", o.agentPort)
409410
serverOption := grpc.Creds(credentials.NewTLS(tlsConfig))
410411
grpcServer := grpc.NewServer(serverOption)
411412
agent.RegisterAgentServiceServer(grpcServer, server)

0 commit comments

Comments
 (0)