Skip to content

Commit c3f692b

Browse files
authored
Merge pull request #1348 from carvel-dev/ra-add-hint-on-cert-error
Adding a hint when the APP CR installation fails due to ca cert error
2 parents e66ee80 + bb08d40 commit c3f692b

File tree

2 files changed

+100
-0
lines changed

2 files changed

+100
-0
lines changed

pkg/app/app_fetch.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,17 @@ import (
88
"fmt"
99
"path"
1010
"strconv"
11+
"strings"
1112
"time"
1213

1314
"github.com/vmware-tanzu/carvel-kapp-controller/pkg/exec"
1415
)
1516

17+
const (
18+
addCACertMissingHintMsg = "(hint: The CA Certificate from URL is unknown/invalid. Add valid CA certificate to the kapp-controller configuration to reconcile successfully)"
19+
caCertMissingError = "x509: certificate signed by unknown authority"
20+
)
21+
1622
func (a *App) fetch(dstPath string) (string, exec.CmdRunResult) {
1723
if len(a.app.Spec.Fetch) == 0 {
1824
return "", exec.NewCmdRunResultWithErr(fmt.Errorf("Expected at least one fetch option"))
@@ -67,6 +73,9 @@ func (a *App) fetch(dstPath string) (string, exec.CmdRunResult) {
6773
}
6874
}
6975
if result.Error != nil {
76+
if strings.Contains(result.Stderr, caCertMissingError) {
77+
result.Stderr = fmt.Sprintf("%s%s", result.Stderr, addCACertMissingHintMsg)
78+
}
7079
return "", result
7180
}
7281
}
@@ -76,6 +85,12 @@ func (a *App) fetch(dstPath string) (string, exec.CmdRunResult) {
7685
dstPath = path.Join(dstPath, "0")
7786
}
7887

88+
if result.Error != nil {
89+
if strings.Contains(result.Stderr, caCertMissingError) {
90+
result.Stderr = fmt.Sprintf("%s%s", result.Stderr, addCACertMissingHintMsg)
91+
}
92+
}
93+
7994
return dstPath, result
8095
}
8196

test/e2e/kappcontroller/config_test.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,3 +422,88 @@ stringData:
422422
assert.Equal(t, actualSyncPeriod, expectedSyncPeriod)
423423
})
424424
}
425+
426+
func TestConfig_NoCACerts(t *testing.T) {
427+
env := e2e.BuildEnv(t)
428+
logger := e2e.Logger{}
429+
kapp := e2e.Kapp{t, env.Namespace, logger}
430+
sas := e2e.ServiceAccounts{env.Namespace}
431+
432+
name := "test-https"
433+
pkgrName := "test-https-pkgr"
434+
httpsServerName := "test-https-server"
435+
configName := "test-config-missing-ca-config"
436+
437+
yaml1 := fmt.Sprintf(`---
438+
apiVersion: kappctrl.k14s.io/v1alpha1
439+
kind: App
440+
metadata:
441+
name: test-https
442+
annotations:
443+
kapp.k14s.io/change-group: kappctrl-e2e.k14s.io/apps
444+
spec:
445+
serviceAccountName: kappctrl-e2e-ns-sa
446+
fetch:
447+
- http:
448+
# use https to exercise CA certificate validation
449+
# When updating address, certs and keys must be regenerated
450+
# for server and added to e2e/assets/https-server
451+
url: https://https-svc.https-server.svc.cluster.local:443/deployment.yml
452+
template:
453+
- ytt: {}
454+
deploy:
455+
- kapp:
456+
inspect: {}
457+
intoNs: %s
458+
`, env.Namespace) + sas.ForNamespaceYAML()
459+
460+
cleanUp := func() {
461+
kapp.Run([]string{"delete", "-a", name})
462+
kapp.Run([]string{"delete", "-a", pkgrName})
463+
kapp.Run([]string{"delete", "-a", configName})
464+
kapp.Run([]string{"delete", "-a", httpsServerName})
465+
}
466+
cleanUp()
467+
defer cleanUp()
468+
469+
logger.Section("deploy controller config with no CA cert", func() {
470+
config := `
471+
apiVersion: v1
472+
kind: Secret
473+
metadata:
474+
name: kapp-controller-config
475+
namespace: kapp-controller
476+
stringData:
477+
# CA Cert is not present
478+
caCerts:
479+
`
480+
kapp.RunWithOpts([]string{"deploy", "-f", "-", "-a", configName},
481+
e2e.RunOpts{StdinReader: strings.NewReader(config)})
482+
483+
// Since config propagation is async, just wait a little bit
484+
time.Sleep(2 * time.Second)
485+
})
486+
487+
logger.Section("deploy https server with self signed certs", func() {
488+
kapp.Run([]string{"deploy", "-f", "../assets/https-server/", "-a", httpsServerName})
489+
})
490+
491+
logger.Section("deploy app that tries to fetch content from https server (whose certs are not uploaded to kapp-controller)", func() {
492+
_, err := kapp.RunWithOpts([]string{"deploy", "-f", "-", "-a", name}, e2e.RunOpts{
493+
StdinReader: strings.NewReader(yaml1),
494+
AllowError: true,
495+
OnErrKubectl: []string{"get", "app/test-https", "-oyaml"},
496+
})
497+
assert.Error(t, err, "Expected fetching error")
498+
499+
var cr v1alpha1.App
500+
501+
out := kapp.Run([]string{"inspect", "-a", name, "--raw", "--tty=false", "--filter-kind=App"})
502+
assert.NoError(t, yaml.Unmarshal([]byte(out), &cr))
503+
504+
assert.NotNil(t, cr.Status.Fetch)
505+
assert.Equal(t, cr.Status.Fetch.ExitCode, 1)
506+
assert.Contains(t, cr.Status.Fetch.Stderr, "x509: certificate signed by unknown authority")
507+
assert.Contains(t, cr.Status.Fetch.Stderr, "(hint: The CA Certificate from URL is unknown/invalid. Add valid CA certificate to the kapp-controller configuration to reconcile successfully)")
508+
})
509+
}

0 commit comments

Comments
 (0)