Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding a hint when the APP CR installation fails due to ca cert error #1348

Merged
merged 1 commit into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions pkg/app/app_fetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,17 @@ import (
"fmt"
"path"
"strconv"
"strings"
"time"

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

const (
addCACertMissingHintMsg = "(hint: The CA Certificate from URL is unknown/invalid. Add valid CA certificate to the kapp-controller configuration to reconcile successfully)"
caCertMissingError = "x509: certificate signed by unknown authority"
rohitagg2020 marked this conversation as resolved.
Show resolved Hide resolved
)

func (a *App) fetch(dstPath string) (string, exec.CmdRunResult) {
if len(a.app.Spec.Fetch) == 0 {
return "", exec.NewCmdRunResultWithErr(fmt.Errorf("Expected at least one fetch option"))
Expand Down Expand Up @@ -67,6 +73,9 @@ func (a *App) fetch(dstPath string) (string, exec.CmdRunResult) {
}
}
if result.Error != nil {
if strings.Contains(result.Stderr, caCertMissingError) {
result.Stderr = fmt.Sprintf("%s%s", result.Stderr, addCACertMissingHintMsg)
}
return "", result
}
}
Expand All @@ -76,6 +85,12 @@ func (a *App) fetch(dstPath string) (string, exec.CmdRunResult) {
dstPath = path.Join(dstPath, "0")
}

if result.Error != nil {
if strings.Contains(result.Stderr, caCertMissingError) {
result.Stderr = fmt.Sprintf("%s%s", result.Stderr, addCACertMissingHintMsg)
}
}

return dstPath, result
}

Expand Down
85 changes: 85 additions & 0 deletions test/e2e/kappcontroller/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -422,3 +422,88 @@ stringData:
assert.Equal(t, actualSyncPeriod, expectedSyncPeriod)
})
}

func TestConfig_NoCACerts(t *testing.T) {
env := e2e.BuildEnv(t)
logger := e2e.Logger{}
kapp := e2e.Kapp{t, env.Namespace, logger}
sas := e2e.ServiceAccounts{env.Namespace}

name := "test-https"
pkgrName := "test-https-pkgr"
httpsServerName := "test-https-server"
configName := "test-config-missing-ca-config"

yaml1 := fmt.Sprintf(`---
apiVersion: kappctrl.k14s.io/v1alpha1
kind: App
metadata:
name: test-https
annotations:
kapp.k14s.io/change-group: kappctrl-e2e.k14s.io/apps
spec:
serviceAccountName: kappctrl-e2e-ns-sa
fetch:
- http:
# use https to exercise CA certificate validation
# When updating address, certs and keys must be regenerated
# for server and added to e2e/assets/https-server
url: https://https-svc.https-server.svc.cluster.local:443/deployment.yml
template:
- ytt: {}
deploy:
- kapp:
inspect: {}
intoNs: %s
`, env.Namespace) + sas.ForNamespaceYAML()

cleanUp := func() {
kapp.Run([]string{"delete", "-a", name})
kapp.Run([]string{"delete", "-a", pkgrName})
kapp.Run([]string{"delete", "-a", configName})
kapp.Run([]string{"delete", "-a", httpsServerName})
}
cleanUp()
defer cleanUp()

logger.Section("deploy controller config with no CA cert", func() {
config := `
apiVersion: v1
kind: Secret
metadata:
name: kapp-controller-config
namespace: kapp-controller
stringData:
# CA Cert is not present
caCerts:
`
kapp.RunWithOpts([]string{"deploy", "-f", "-", "-a", configName},
e2e.RunOpts{StdinReader: strings.NewReader(config)})

// Since config propagation is async, just wait a little bit
time.Sleep(2 * time.Second)
})

logger.Section("deploy https server with self signed certs", func() {
kapp.Run([]string{"deploy", "-f", "../assets/https-server/", "-a", httpsServerName})
})

logger.Section("deploy app that tries to fetch content from https server (whose certs are not uploaded to kapp-controller)", func() {
_, err := kapp.RunWithOpts([]string{"deploy", "-f", "-", "-a", name}, e2e.RunOpts{
StdinReader: strings.NewReader(yaml1),
AllowError: true,
OnErrKubectl: []string{"get", "app/test-https", "-oyaml"},
})
assert.Error(t, err, "Expected fetching error")

var cr v1alpha1.App

out := kapp.Run([]string{"inspect", "-a", name, "--raw", "--tty=false", "--filter-kind=App"})
assert.NoError(t, yaml.Unmarshal([]byte(out), &cr))

assert.NotNil(t, cr.Status.Fetch)
assert.Equal(t, cr.Status.Fetch.ExitCode, 1)
assert.Contains(t, cr.Status.Fetch.Stderr, "x509: certificate signed by unknown authority")
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)")
})
}