Fix google calendar key validation (#44556)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #42886 # Checklist for submitter If some of the following don't apply, delete the relevant line. - [X] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. ## Testing - [X] Added/updated automated tests - [X] QA'd all new/changed functionality manually - [X] gitops run with extra keys (besides `client_email` and `private_key` in `api_key_json` fails on main, passes on this branch - [X] gitops run with missing `client_email` or `private_key` in `api_key_json` still fails gitops (including dry run) - [X] gitops run with extra keys sibling to api_key_json still fails as expected <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Corrected GitOps validation so Google Calendar API key JSON no longer rejects valid nested keys; required-field validation for the integration still enforced. * **Tests** * Added test coverage to ensure nested unknown keys are accepted while sibling-level unknown fields are reported as validation errors. [](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/44556) <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Tim Lee <timlee@fleetdm.com>
This commit is contained in:
co-authored by
Copilot Autofix powered by AI
Tim Lee
parent
c6407f9d24
commit
f5c59ae3b4
@@ -0,0 +1 @@
|
||||
- Fixed issue where GitOps would incorrectly reject keys in Google Calendar API key JSON
|
||||
@@ -129,16 +129,25 @@ func TestValidateUnknownKeys(t *testing.T) {
|
||||
assert.Len(t, errs, 2)
|
||||
})
|
||||
|
||||
t.Run("ValidKeysProvider accepts declared keys", func(t *testing.T) {
|
||||
// GoogleCalendarApiKey implements ValidKeysProvider to declare accepted
|
||||
// keys for its custom JSON marshaling.
|
||||
t.Run("api_key_json keys are not validated", func(t *testing.T) {
|
||||
// GoogleCalendarApiKey accepts the full Google service-account JSON blob,
|
||||
// so unknown-key validation is intentionally skipped for its contents.
|
||||
data := map[string]any{
|
||||
"google_calendar": []any{
|
||||
map[string]any{
|
||||
"domain": "example.com",
|
||||
"api_key_json": map[string]any{
|
||||
"client_email": "test@example.com",
|
||||
"private_key": "some value",
|
||||
"client_email": "test@example.com",
|
||||
"private_key": "some value",
|
||||
"type": "service_account",
|
||||
"project_id": "fleet-dogfood",
|
||||
"private_key_id": "abc123",
|
||||
"client_id": "1234567890",
|
||||
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
||||
"token_uri": "https://oauth2.googleapis.com/token",
|
||||
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
||||
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/foo",
|
||||
"universe_domain": "googleapis.com",
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -147,22 +156,20 @@ func TestValidateUnknownKeys(t *testing.T) {
|
||||
assert.Empty(t, errs)
|
||||
})
|
||||
|
||||
t.Run("ValidKeysProvider rejects undeclared keys", func(t *testing.T) {
|
||||
t.Run("unknown keys at google_calendar entry level are rejected", func(t *testing.T) {
|
||||
// Skipping validation for api_key_json must not leak into siblings.
|
||||
data := map[string]any{
|
||||
"google_calendar": []any{
|
||||
map[string]any{
|
||||
"domain": "example.com",
|
||||
"api_key_json": map[string]any{
|
||||
"client_email": "test@example.com",
|
||||
"private_key": "nothing to see here",
|
||||
"bad_field": "unknown",
|
||||
},
|
||||
"domain": "example.com",
|
||||
"api_key_json": map[string]any{"client_email": "x", "private_key": "y"},
|
||||
"bad_sibling": true,
|
||||
},
|
||||
},
|
||||
}
|
||||
errs := validateUnknownKeys(data, reflect.TypeFor[fleet.Integrations](), []string{"org_settings", "integrations"}, "test.yml")
|
||||
require.Len(t, errs, 1)
|
||||
assert.Contains(t, errs[0].Error(), "bad_field")
|
||||
assert.Contains(t, errs[0].Error(), "bad_sibling")
|
||||
})
|
||||
|
||||
t.Run("scalar data no errors", func(t *testing.T) {
|
||||
|
||||
@@ -389,14 +389,15 @@ const (
|
||||
GoogleCalendarPrivateKey = "private_key"
|
||||
)
|
||||
|
||||
// googleCalendarKeyNames lists all valid JSON keys for GoogleCalendarApiKey,
|
||||
// used by ValidKeys() for gitops unknown-key validation.
|
||||
var googleCalendarKeyNames = []string{GoogleCalendarEmail, GoogleCalendarPrivateKey}
|
||||
|
||||
// GoogleCalendarApiKey is a custom type for the Google Calendar API key JSON.
|
||||
// It handles JSON marshaling/unmarshaling with support for masking sensitive data.
|
||||
// When marshaled in masked state, it serializes to just "********".
|
||||
// When unmarshaled, it accepts either "********" (indicating masked/preserve) or a JSON object.
|
||||
//
|
||||
// GitOps unknown-key validation is intentionally skipped for this type: users
|
||||
// typically paste the full Google service-account JSON blob (which contains many
|
||||
// keys beyond the two Fleet uses), and ValidateGoogleCalendarIntegrations still
|
||||
// enforces that client_email and private_key are present.
|
||||
type GoogleCalendarApiKey struct {
|
||||
// Values contains the actual API key fields when not masked
|
||||
Values map[string]string
|
||||
@@ -404,13 +405,6 @@ type GoogleCalendarApiKey struct {
|
||||
masked bool
|
||||
}
|
||||
|
||||
// ValidKeys returns the set of accepted JSON keys for this type.
|
||||
// This is used by gitops validation to check for unknown keys in types
|
||||
// with custom JSON marshaling.
|
||||
func (GoogleCalendarApiKey) ValidKeys() []string {
|
||||
return googleCalendarKeyNames
|
||||
}
|
||||
|
||||
// MarshalJSON implements json.Marshaler. When masked, returns "********".
|
||||
// Otherwise, returns the JSON object representation of the values.
|
||||
func (k GoogleCalendarApiKey) MarshalJSON() ([]byte, error) {
|
||||
|
||||
Reference in New Issue
Block a user