Support generate-gitops for android certificates (#36457)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** Resolves #36436 # Details Implements outputting `android_settings.certificates` when running `fleetctl generate-gitops`. # Checklist for submitter ## Testing - [X] Added/updated automated tests - [X] QA'd all new/changed functionality manually * Added a certificate authority via the UI, then added some certificates via GitOps, and verified that the certificates were outputted correctly when using `fleetctl generate-gitops`.
This commit is contained in:
@@ -83,6 +83,8 @@ type generateGitopsClient interface {
|
||||
GetSetupExperienceScript(teamID uint) (*fleet.Script, error)
|
||||
GetAppleMDMEnrollmentProfile(teamID uint) (*fleet.MDMAppleSetupAssistant, error)
|
||||
GetCertificateAuthoritiesSpec(includeSecrets bool) (*fleet.GroupedCertificateAuthorities, error)
|
||||
GetCertificateTemplates(teamID string) ([]*fleet.CertificateTemplateResponseSummary, error)
|
||||
GetCertificateTemplate(certificateID uint, hostUUID *string) (*fleet.CertificateTemplateResponseFull, error)
|
||||
}
|
||||
|
||||
// Given a struct type and a field name, return the JSON field name.
|
||||
@@ -1064,9 +1066,46 @@ func (cmd *GenerateGitopsCommand) generateControls(teamId *uint, teamName string
|
||||
}
|
||||
}
|
||||
|
||||
if cmd.AppConfig.License.IsPremium() {
|
||||
mdmT := reflect.TypeOf(fleet.TeamMDM{})
|
||||
// Get any Android certificate templates.
|
||||
var certSummaries []*fleet.CertificateTemplateResponseSummary
|
||||
var err error
|
||||
if teamId == nil {
|
||||
certSummaries, err = cmd.Client.GetCertificateTemplates("")
|
||||
} else {
|
||||
certSummaries, err = cmd.Client.GetCertificateTemplates(strconv.FormatUint(uint64(*teamId), 10))
|
||||
}
|
||||
if err != nil {
|
||||
fmt.Fprintf(cmd.CLI.App.ErrWriter, "Error getting certificate templates: %s\n", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mdmT := reflect.TypeOf(fleet.TeamMDM{})
|
||||
|
||||
if len(certSummaries) > 0 {
|
||||
androidSettingsType := reflect.TypeOf(fleet.AndroidSettings{})
|
||||
certType := reflect.TypeOf(fleet.CertificateTemplateResponseFull{})
|
||||
fullCerts := make([]map[string]interface{}, 0, len(certSummaries))
|
||||
for _, certSummary := range certSummaries {
|
||||
certFull, err := cmd.Client.GetCertificateTemplate(certSummary.ID, nil)
|
||||
if err != nil {
|
||||
fmt.Fprintf(cmd.CLI.App.ErrWriter, "Error getting certificate template details for ID %d: %s\n", certSummary.ID, err)
|
||||
return nil, err
|
||||
}
|
||||
fullCerts = append(fullCerts, map[string]interface{}{
|
||||
jsonFieldName(certType, "Name"): certFull.Name,
|
||||
jsonFieldName(certType, "CertificateAuthorityName"): certFull.CertificateAuthorityName,
|
||||
jsonFieldName(certType, "SubjectName"): certFull.SubjectName,
|
||||
})
|
||||
}
|
||||
androidSettings, ok := result[jsonFieldName(mdmT, "AndroidSettings")].(map[string]interface{})
|
||||
if !ok {
|
||||
androidSettings = map[string]interface{}{}
|
||||
}
|
||||
androidSettings[jsonFieldName(androidSettingsType, "Certificates")] = fullCerts
|
||||
result[jsonFieldName(mdmT, "AndroidSettings")] = androidSettings
|
||||
}
|
||||
|
||||
if cmd.AppConfig.License.IsPremium() {
|
||||
if teamMdm != nil {
|
||||
result[jsonFieldName(mdmT, "EnableDiskEncryption")] = teamMdm.EnableDiskEncryption
|
||||
result[jsonFieldName(mdmT, "RequireBitLockerPIN")] = teamMdm.RequireBitLockerPIN
|
||||
|
||||
@@ -581,6 +581,35 @@ func (MockClient) GetCertificateAuthoritiesSpec(includeSecrets bool) (*fleet.Gro
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
func (MockClient) GetCertificateTemplates(teamID string) ([]*fleet.CertificateTemplateResponseSummary, error) {
|
||||
var res []*fleet.CertificateTemplateResponseSummary
|
||||
if teamID == "1" {
|
||||
res = []*fleet.CertificateTemplateResponseSummary{
|
||||
{
|
||||
ID: 1,
|
||||
CertificateAuthorityName: "DIGIDOO",
|
||||
Name: "my_certypoo",
|
||||
},
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (MockClient) GetCertificateTemplate(certificateID uint, hostUUID *string) (*fleet.CertificateTemplateResponseFull, error) {
|
||||
var res *fleet.CertificateTemplateResponseFull
|
||||
if certificateID == 1 {
|
||||
res = &fleet.CertificateTemplateResponseFull{
|
||||
CertificateTemplateResponseSummary: fleet.CertificateTemplateResponseSummary{
|
||||
ID: 1,
|
||||
CertificateAuthorityName: "DIGIDOO",
|
||||
Name: "my_certypoo",
|
||||
},
|
||||
SubjectName: "CN=OU=$FLEET_VAR_HOST_UUID/ST=$FLEET_VAR_HOST_HARDWARE_SERIAL",
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func maskSecret(value string, shouldShowSecret bool) string {
|
||||
if shouldShowSecret {
|
||||
return value
|
||||
|
||||
@@ -2,4 +2,9 @@ macos_settings:
|
||||
custom_settings:
|
||||
- path: ../lib/some_team/profiles/team-macos-mobileconfig-profile.mobileconfig
|
||||
scripts:
|
||||
- path: ../lib/some_team/scripts/Script B.ps1
|
||||
- path: ../lib/some_team/scripts/Script B.ps1
|
||||
android_settings:
|
||||
certificates:
|
||||
- certificate_authority_name: DIGIDOO
|
||||
name: my_certypoo
|
||||
subject_name: CN=OU=$FLEET_VAR_HOST_UUID/ST=$FLEET_VAR_HOST_HARDWARE_SERIAL
|
||||
@@ -134,6 +134,15 @@
|
||||
},
|
||||
"windows_settings": {
|
||||
"custom_settings": null
|
||||
},
|
||||
"android_settings": {
|
||||
"certificates": [
|
||||
{
|
||||
"certificate_authority_name": "DIGIDOO",
|
||||
"name": "my_certypoo",
|
||||
"subject_name": "CN=OU=$FLEET_VAR_HOST_UUID/ST=$FLEET_VAR_HOST_HARDWARE_SERIAL"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"scripts": [
|
||||
|
||||
+5
@@ -18,6 +18,11 @@ agent_options:
|
||||
osqueryd: edge
|
||||
controls:
|
||||
android_enabled_and_configured: true
|
||||
android_settings:
|
||||
certificates:
|
||||
- certificate_authority_name: DIGIDOO
|
||||
name: my_certypoo
|
||||
subject_name: CN=OU=$FLEET_VAR_HOST_UUID/ST=$FLEET_VAR_HOST_HARDWARE_SERIAL
|
||||
enable_disk_encryption: true
|
||||
ios_updates:
|
||||
deadline: "2021-12-31"
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/fleetdm/fleet/v4/server/fleet"
|
||||
)
|
||||
|
||||
@@ -16,6 +18,22 @@ func (c *Client) GetCertificateTemplates(teamID string) ([]*fleet.CertificateTem
|
||||
return responseBody.Certificates, nil
|
||||
}
|
||||
|
||||
// GetCertificateTemplate retrieves the full details of a single certificate, optionally
|
||||
// replacing vars in the subject with values from a specified host.
|
||||
func (c *Client) GetCertificateTemplate(certificateID uint, hostUUID *string) (*fleet.CertificateTemplateResponseFull, error) {
|
||||
verb, path := "GET", "/api/latest/fleet/certificates/"+strconv.FormatUint(uint64(certificateID), 10)
|
||||
var responseBody getCertificateTemplateResponse
|
||||
var query string
|
||||
if hostUUID != nil {
|
||||
query = "host_uuid=" + *hostUUID
|
||||
}
|
||||
err := c.authenticatedRequestWithQuery(nil, verb, path, &responseBody, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return responseBody.Certificate, nil
|
||||
}
|
||||
|
||||
// ApplyCertificateSpecs sends a list of certificate specs to the fleet instance to be added/updated.
|
||||
func (c *Client) ApplyCertificateSpecs(specs []*fleet.CertificateRequestSpec) error {
|
||||
req := applyCertificateTemplateSpecsRequest{Specs: specs}
|
||||
|
||||
Reference in New Issue
Block a user