fleet/server/mdm/android/onc_test.go
Victor Lyuboslavsky 36ad83f611
Android Wi-Fi profile withheld until cert installed on device (#42877)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #42405

Demo video: https://www.youtube.com/watch?v=F3nfFvwdj-c

# 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`.

## Testing

- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Android Wi‑Fi configuration profiles that reference client
certificates are withheld until the certificate is installed or reaches
a terminal state.
* Host OS settings now show the specific pending reason in the detail
column when Android profiles are waiting on certificate installation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-04-07 16:26:09 -05:00

172 lines
3.3 KiB
Go

package android
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestExtractCertAliasesFromONC(t *testing.T) {
tests := []struct {
name string
oncJSON string
expected []string
wantErr bool
}{
{
name: "WiFi EAP with KeyPairAlias",
oncJSON: `{
"NetworkConfigurations": [{
"WiFi": {
"EAP": {
"ClientCertType": "KeyPairAlias",
"ClientCertKeyPairAlias": "wifi-cert"
}
}
}]
}`,
expected: []string{"wifi-cert"},
},
{
name: "VPN with KeyPairAlias",
oncJSON: `{
"NetworkConfigurations": [{
"VPN": {
"ClientCertType": "KeyPairAlias",
"ClientCertKeyPairAlias": "vpn-cert"
}
}]
}`,
expected: []string{"vpn-cert"},
},
{
name: "WiFi without EAP (WPA-PSK)",
oncJSON: `{
"NetworkConfigurations": [{
"WiFi": {
"SSID": "GuestNet",
"Security": "WPA-PSK",
"Passphrase": "guest123"
}
}]
}`,
expected: nil,
},
{
name: "alias present but ClientCertType is Ref (ignored per ONC spec)",
oncJSON: `{
"NetworkConfigurations": [{
"WiFi": {
"EAP": {
"ClientCertType": "Ref",
"ClientCertKeyPairAlias": "should-be-ignored"
}
}
}]
}`,
expected: nil,
},
{
name: "alias present but ClientCertType is missing (ignored per ONC spec)",
oncJSON: `{
"NetworkConfigurations": [{
"WiFi": {
"EAP": {
"ClientCertKeyPairAlias": "should-be-ignored"
}
}
}]
}`,
expected: nil,
},
{
name: "mix of KeyPairAlias and other ClientCertTypes",
oncJSON: `{
"NetworkConfigurations": [
{
"WiFi": {
"EAP": {
"ClientCertType": "KeyPairAlias",
"ClientCertKeyPairAlias": "real-cert"
}
}
},
{
"VPN": {
"ClientCertType": "Ref",
"ClientCertKeyPairAlias": "ignored-cert"
}
}
]
}`,
expected: []string{"real-cert"},
},
{
name: "invalid JSON",
oncJSON: `{invalid}`,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
aliases, err := ExtractCertAliasesFromONC(json.RawMessage(tt.oncJSON))
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
assert.Equal(t, tt.expected, aliases)
})
}
}
func TestExtractCertAliasesFromProfileJSON(t *testing.T) {
tests := []struct {
name string
profileJSON string
expected []string
wantErr bool
}{
{
name: "profile with ONC containing cert ref",
profileJSON: `{
"openNetworkConfiguration": {
"NetworkConfigurations": [{
"WiFi": {
"EAP": {
"ClientCertType": "KeyPairAlias",
"ClientCertKeyPairAlias": "my-cert"
}
}
}]
}
}`,
expected: []string{"my-cert"},
},
{
name: "profile without ONC field",
profileJSON: `{"cameraDisabled": true, "maximumTimeToLock": 300}`,
expected: nil,
},
{
name: "invalid JSON",
profileJSON: `not json`,
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
aliases, err := ExtractCertAliasesFromProfileJSON(json.RawMessage(tt.profileJSON))
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
assert.Equal(t, tt.expected, aliases)
})
}
}