mirror of
https://github.com/empayre/fleet.git
synced 2024-11-06 08:55:24 +00:00
Add a tool to generate manifests for Apple MDM (#10959)
Related to #9459 this will allow us to host a `fleetd` metadata alongside the installer that can be used by Apple's MDM `InstallEnterpriseApplication`
This commit is contained in:
parent
ee135fe06b
commit
ab583d66e6
39
server/mdm/apple/appmanifest/appmanifest.go
Normal file
39
server/mdm/apple/appmanifest/appmanifest.go
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// package appmanifest provides utilities for managing app manifest files
|
||||||
|
// used by MDM InstallApplication commands.
|
||||||
|
//
|
||||||
|
// It's heavily based on the micromdm/mdm/appmanifest package but it uses
|
||||||
|
// SHA256 as the hashing algorithm instead of MD5.
|
||||||
|
package appmanifest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/micromdm/micromdm/mdm/appmanifest"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Create builds an AppManifest using SHA256 checksums and the provided URL
|
||||||
|
func Create(file io.Reader, url string) (*appmanifest.Manifest, error) {
|
||||||
|
hash := sha256.New()
|
||||||
|
if _, err := io.Copy(hash, file); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
sum := fmt.Sprintf("%x", hash.Sum(nil))
|
||||||
|
|
||||||
|
ast := appmanifest.Asset{
|
||||||
|
Kind: "software-package",
|
||||||
|
SHA256Size: int64(hash.Size()),
|
||||||
|
SHA256s: []string{sum},
|
||||||
|
URL: url,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &appmanifest.Manifest{
|
||||||
|
ManifestItems: []appmanifest.Item{
|
||||||
|
{
|
||||||
|
Assets: []appmanifest.Asset{ast},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
|
}
|
52
server/mdm/apple/appmanifest/appmanifest_test.go
Normal file
52
server/mdm/apple/appmanifest/appmanifest_test.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package appmanifest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/micromdm/micromdm/mdm/appmanifest"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
var errTest = errors.New("test error")
|
||||||
|
|
||||||
|
type alwaysFailReader struct{}
|
||||||
|
|
||||||
|
func (alwaysFailReader) Read(p []byte) (n int, err error) {
|
||||||
|
return 0, errTest
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreate(t *testing.T) {
|
||||||
|
url := "https://test.example.com"
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
in io.Reader
|
||||||
|
out *appmanifest.Manifest
|
||||||
|
err error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
in: strings.NewReader("foo"),
|
||||||
|
out: &appmanifest.Manifest{
|
||||||
|
ManifestItems: []appmanifest.Item{{Assets: []appmanifest.Asset{{
|
||||||
|
Kind: "software-package",
|
||||||
|
SHA256Size: 32,
|
||||||
|
SHA256s: []string{"2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae"},
|
||||||
|
URL: "https://test.example.com",
|
||||||
|
}}}}},
|
||||||
|
err: nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
in: alwaysFailReader{},
|
||||||
|
out: nil,
|
||||||
|
err: errTest,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range cases {
|
||||||
|
m, err := Create(c.in, url)
|
||||||
|
require.Equal(t, c.out, m)
|
||||||
|
require.Equal(t, c.err, err)
|
||||||
|
}
|
||||||
|
}
|
36
tools/mdm/apple/appmanifest/README.md
Normal file
36
tools/mdm/apple/appmanifest/README.md
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
## appmanifest
|
||||||
|
|
||||||
|
`appmanifest` is a tool that outputs to stdout a valid XML manifest that can be used by the MDM `InstallEnterpriseApplication` command to install a package.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ go run tools/mdm/apple/appmanifest/main.go --help
|
||||||
|
Usage of appmanifest:
|
||||||
|
-pkg-file string
|
||||||
|
Path to a .pkg file
|
||||||
|
-pkg-url string
|
||||||
|
URL where the package will be served
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example workflow
|
||||||
|
|
||||||
|
1. Create a fleetd installer
|
||||||
|
|
||||||
|
```
|
||||||
|
fleetctl package --type=pkg --fleet-desktop
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Sign the installer so it can be installed via MDM
|
||||||
|
|
||||||
|
```
|
||||||
|
productsign --sign "Developer ID Installer: $DEVID_INFO" fleet-osquery.pkg fleetd-base.pkg
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Run `appmanifest`
|
||||||
|
|
||||||
|
```
|
||||||
|
$ go run tools/mdm/apple/appmanifest/main.go \
|
||||||
|
-pkg-file fleetd-base.pkg \
|
||||||
|
-pkg-url $YOUR_URL > fleetd-base-manifest.plist
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Upload `fleetd-base.pkg` to `$YOUR_URL` and `fleetd-base-manifest.plist` to a publicly accessible location.
|
43
tools/mdm/apple/appmanifest/main.go
Normal file
43
tools/mdm/apple/appmanifest/main.go
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// Command appmanifest takes a .pkg file and outputs an XML manifest for it
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/fleetdm/fleet/v4/server/mdm/apple/appmanifest"
|
||||||
|
"github.com/groob/plist"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
pkgFile := flag.String("pkg-file", "", "Path to a .pkg file")
|
||||||
|
pkgURL := flag.String("pkg-url", "", "URL where the package will be served")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if *pkgFile == "" || *pkgURL == "" {
|
||||||
|
log.Fatal("both --pkg-file and --pkg-url must be provided")
|
||||||
|
}
|
||||||
|
|
||||||
|
fp, err := os.Open(*pkgFile)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer fp.Close()
|
||||||
|
|
||||||
|
m, err := appmanifest.Create(fp, *pkgURL)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
enc := plist.NewEncoder(&buf)
|
||||||
|
enc.Indent(" ")
|
||||||
|
if err := enc.Encode(m); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(buf.String())
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user