Skip to content

Commit 92d42a1

Browse files
authored
chore: detect splitbrain (#463)
* detect splitbrain * make /.kube writable * add emptyDir volume for /.kube
1 parent 4a22840 commit 92d42a1

File tree

5 files changed

+30
-18
lines changed

5 files changed

+30
-18
lines changed

Dockerfile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ RUN curl -L https://get.helm.sh/helm-${HELM_VERSION}-linux-${TARGETARCH}.tar.gz
3131
FROM alpine:3.21
3232
WORKDIR /workspace
3333

34-
RUN mkdir /.kube && chown 65532:65532 /.kube
34+
RUN mkdir /.kube && \
35+
chown 65532:65532 /.kube && \
36+
chmod 700 /.kube
3537

3638
COPY --from=builder /workspace/deployment-agent .
3739
# Copy Helm binary from builder

charts/deployment-operator/templates/deployment.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ spec:
6767
volumeMounts:
6868
- name: temp
6969
mountPath: /tmp
70+
- name: kube-dir
71+
mountPath: /.kube
72+
readOnly: false
7073
{{- range $cert := .Values.certs }}
7174
- name: {{ $cert.name }}
7275
mountPath: "/etc/ssl/certs/{{ $cert.file }}"
@@ -154,6 +157,8 @@ spec:
154157
volumes:
155158
- name: temp
156159
emptyDir: {}
160+
- name: kube-dir
161+
emptyDir: {}
157162
- name: service-account-token-volume
158163
projected:
159164
defaultMode: 0444

pkg/manifests/cache.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func (c *ManifestCache) Fetch(svc *console.ServiceDeploymentForAgent) (string, e
6161
return "", err
6262
}
6363

64-
dir, err := fetch(tarballURL.String(), c.token)
64+
dir, err := fetch(tarballURL.String(), c.token, sha)
6565
if err != nil {
6666
return "", err
6767
}

pkg/manifests/tarball.go

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import (
99
"time"
1010
)
1111

12+
const pluralDigestHeader = "x-plrl-digest"
13+
1214
var (
1315
timeout = 60 * time.Second
1416
client = &http.Client{
@@ -20,7 +22,7 @@ var (
2022
)
2123

2224
func getBody(url, token string) (string, error) {
23-
resp, err := getReader(url, token)
25+
resp, _, err := getReader(url, token)
2426
if err != nil {
2527
return "", err
2628
}
@@ -35,33 +37,33 @@ func getBody(url, token string) (string, error) {
3537
return string(body), nil
3638
}
3739

38-
func getReader(url, token string) (io.ReadCloser, error) {
40+
func getReader(url, token string) (io.ReadCloser, http.Header, error) {
3941
req, err := http.NewRequest(http.MethodGet, url, nil)
4042
if err != nil {
41-
return nil, err
43+
return nil, nil, err
4244
}
4345
req.Header.Add("Authorization", "Token "+token)
4446

4547
for i := 0; i < 3; i++ {
46-
resp, retriable, err := doRequest(req)
48+
resp, header, retriable, err := doRequest(req)
4749
if err != nil {
4850
if !retriable {
49-
return nil, err
51+
return nil, nil, err
5052
}
5153

5254
time.Sleep(time.Duration(50*(i+1)) * time.Millisecond)
5355
continue
5456
}
5557

56-
return resp, nil
58+
return resp, header, nil
5759
}
58-
return nil, fmt.Errorf("could not fetch manifest, retries exhaused: %w", err)
60+
return nil, nil, fmt.Errorf("could not fetch manifest, retries exhaused: %w", err)
5961
}
6062

61-
func doRequest(req *http.Request) (io.ReadCloser, bool, error) {
63+
func doRequest(req *http.Request) (io.ReadCloser, http.Header, bool, error) {
6264
resp, err := client.Do(req)
6365
if err != nil {
64-
return nil, false, err
66+
return nil, nil, false, err
6567
}
6668

6769
if resp.StatusCode != http.StatusOK {
@@ -71,13 +73,13 @@ func doRequest(req *http.Request) (io.ReadCloser, bool, error) {
7173
err := fmt.Errorf("could not fetch manifest, error code %d", resp.StatusCode)
7274

7375
if resp.StatusCode == http.StatusTooManyRequests {
74-
return nil, true, err
76+
return nil, nil, true, err
7577
}
7678

77-
return nil, false, err
79+
return nil, nil, false, err
7880
}
7981

80-
return resp.Body, false, nil
82+
return resp.Body, resp.Header, false, nil
8183
}
8284

8385
func fetchSha(consoleURL, token, serviceID string) (string, error) {
@@ -89,18 +91,21 @@ func fetchSha(consoleURL, token, serviceID string) (string, error) {
8991
return getBody(url, token)
9092
}
9193

92-
func fetch(url, token string) (string, error) {
94+
func fetch(url, token, sha string) (string, error) {
9395
dir, err := os.MkdirTemp("", "manifests")
9496
if err != nil {
9597
return "", err
9698
}
9799

98-
resp, err := getReader(url, token)
100+
resp, header, err := getReader(url, token)
99101
if err != nil {
100102
return "", err
101103
}
102-
103104
defer resp.Close()
105+
tarballSha := header.Get(pluralDigestHeader)
106+
if tarballSha != "" && sha != tarballSha {
107+
return "", fmt.Errorf("tarball sha expected %s actual %s", sha, tarballSha)
108+
}
104109

105110
log.V(1).Info("finished request to", "url", url)
106111

pkg/manifests/tarball_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func TestFetch_Success(t *testing.T) {
9797
}))
9898
defer server.Close()
9999

100-
dir, err := fetch(server.URL, "dummy-token")
100+
dir, err := fetch(server.URL, "dummy-token", "")
101101
if err != nil {
102102
t.Fatalf("fetch failed: %v", err)
103103
}

0 commit comments

Comments
 (0)