mirror of
https://github.com/micromdm/micromdm/
synced 2026-08-10 19:46:07 +08:00
implement mdmctl apply app -sign-identity (#785)
* implement mdmctl apply app -sign-identity * update go-cpio-odc for macOS compatibility * update go-cpio-odc for windows compatibility * update go-cpio-odc to satisfy builder
This commit is contained in:
@@ -25,13 +25,16 @@ func (cmd *applyCommand) applyApp(args []string) error {
|
||||
flagset := flag.NewFlagSet("app", flag.ExitOnError)
|
||||
var (
|
||||
flPkgPath = flagset.String("pkg", "", "path to a distribution pkg.")
|
||||
flOutputPath = flagset.String("out", "", "pkg output path for -sign and -sign-identity (optional, defaults to OS temporary directory)")
|
||||
flPkgURL = flagset.String("pkg-url", "", "use custom pkg url")
|
||||
flAppManifest = flagset.String("manifest", "-", `path to an app manifest. optional,
|
||||
will be created if file does not exist.`)
|
||||
|
||||
flHashSize = flagset.Int64("md5size", appmanifest.DefaultMD5Size, "md5 hash size in bytes (optional)")
|
||||
flSign = flagset.String("sign", "", "sign package before importing, requires specifying a product ID (optional)")
|
||||
flUpload = flagset.Bool("upload", false, "upload package and/or manifest to micromdm repository.")
|
||||
flHashSize = flagset.Int64("md5size", appmanifest.DefaultMD5Size, "md5 hash size in bytes (optional)")
|
||||
flSign = flagset.String("sign", "", "sign package before importing, requires specifying id of developer identity in keychain (optional, macOS only)")
|
||||
flSignIdentity = flagset.String("sign-identity", "", "sign package before importing, requires specifying path to .p12 developer identity (optional)")
|
||||
flIdentityPass = flagset.String("password", "", "password used for -sign-identity (optional)")
|
||||
flUpload = flagset.Bool("upload", false, "upload package and/or manifest to micromdm repository.")
|
||||
)
|
||||
flagset.Usage = usageFor(flagset, "mdmctl apply app [flags]")
|
||||
if err := flagset.Parse(args); err != nil {
|
||||
@@ -70,13 +73,27 @@ Please rebuild the package and re-run the command.
|
||||
}
|
||||
|
||||
if !signed {
|
||||
if *flSign == "" {
|
||||
if *flSign == "" && *flSignIdentity == "" {
|
||||
flagset.Usage()
|
||||
return errors.New(`MDM packages must be signed. Provide signed package or Developer ID with -sign flag`)
|
||||
return errors.New(`MDM packages must be signed. Provide signed package or -sign or -sign-identity flags`)
|
||||
}
|
||||
outpath := filepath.Join(os.TempDir(), filepath.Base(*flPkgPath))
|
||||
if err := signPackage(*flPkgPath, outpath, *flSign); err != nil {
|
||||
return err
|
||||
outpath := *flOutputPath
|
||||
if outpath == "" {
|
||||
outpath = filepath.Join(os.TempDir(), filepath.Base(*flPkgPath))
|
||||
}
|
||||
if outpath == *flPkgPath {
|
||||
return errors.New("-out can't be the same as -pkg")
|
||||
}
|
||||
|
||||
if *flSign != "" {
|
||||
if err := signPackage(*flPkgPath, outpath, *flSign); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := signPackageWithIdentity(*flPkgPath, outpath, *flSignIdentity, *flIdentityPass); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
}
|
||||
pkg = outpath // use signed package to create the manifest
|
||||
}
|
||||
|
||||
@@ -3,14 +3,31 @@
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
goerrors "errors"
|
||||
|
||||
macospkg "github.com/korylprince/go-macos-pkg"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func signPackage(path, outpath, developerID string) error {
|
||||
fmt.Println("[WARNING] package signing only implemented on macOS")
|
||||
fmt.Println("[WARNING] package signing with -sign only implemented on macOS. Use -sign-identity instead")
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkSignature(pkgpath string) (bool, error) {
|
||||
fmt.Println("[WARNING] package signing only implemented on macOS. An unsigned macOS package will not install with MDM.")
|
||||
buf, err := os.ReadFile(pkgpath)
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "reading package")
|
||||
}
|
||||
if err = macospkg.VerifyPkg(buf); err != nil {
|
||||
if goerrors.Is(err, macospkg.ErrNotSigned) {
|
||||
return false, nil
|
||||
}
|
||||
return false, errors.Wrap(err, "verifying package")
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
36
cmd/mdmctl/sign_identity.go
Normal file
36
cmd/mdmctl/sign_identity.go
Normal file
@@ -0,0 +1,36 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/rsa"
|
||||
"os"
|
||||
|
||||
macospkg "github.com/korylprince/go-macos-pkg"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/crypto/pkcs12"
|
||||
)
|
||||
|
||||
func signPackageWithIdentity(pkgpath, outpath, identitypath, identitypass string) error {
|
||||
identity, err := os.ReadFile(identitypath)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "reading identity")
|
||||
}
|
||||
key, cert, err := pkcs12.Decode(identity, identitypass)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "decoding identity")
|
||||
}
|
||||
|
||||
pkg, err := os.ReadFile(pkgpath)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "reading package")
|
||||
}
|
||||
|
||||
signed, err := macospkg.SignPkg(pkg, cert, key.(*rsa.PrivateKey))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "signing package")
|
||||
}
|
||||
|
||||
if err = os.WriteFile(outpath, signed, 0644); err != nil {
|
||||
return errors.Wrap(err, "writing signed package")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
9
go.mod
9
go.mod
@@ -12,14 +12,15 @@ require (
|
||||
github.com/groob/plist v0.0.0-20220217120414-63fa881b19a5
|
||||
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0
|
||||
github.com/kolide/kit v0.0.0-20180912215818-0c28f72eb2b0
|
||||
github.com/korylprince/go-macos-pkg v1.3.5
|
||||
github.com/lib/pq v1.0.0
|
||||
github.com/micromdm/go4 v0.0.0-20210104222236-8a0936d9e451
|
||||
github.com/micromdm/scep/v2 v2.1.0
|
||||
github.com/pkg/errors v0.8.0
|
||||
github.com/pressly/goose v2.3.0+incompatible
|
||||
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974
|
||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110
|
||||
google.golang.org/protobuf v1.27.1
|
||||
gopkg.in/Masterminds/squirrel.v1 v1.0.0-20170825200431-a6b93000bd21
|
||||
)
|
||||
@@ -31,6 +32,8 @@ require (
|
||||
github.com/go-sql-driver/mysql v1.4.0 // indirect
|
||||
github.com/go-stack/stack v1.7.0 // indirect
|
||||
github.com/gorilla/context v1.1.1 // indirect
|
||||
github.com/korylprince/go-cpio-odc v0.9.4 // indirect
|
||||
github.com/korylprince/goxar v0.0.0-20211111233330-e9f257bcdf25 // indirect
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 // indirect
|
||||
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
|
||||
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
|
||||
@@ -38,7 +41,7 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/stretchr/testify v1.2.2 // indirect
|
||||
github.com/ziutek/mymysql v1.5.4 // indirect
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f // indirect
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect
|
||||
golang.org/x/text v0.3.3 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
google.golang.org/appengine v1.2.0 // indirect
|
||||
|
||||
23
go.sum
23
go.sum
@@ -44,6 +44,16 @@ github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0 h1:5B0uxl2lzNRVkJVg+u
|
||||
github.com/jmoiron/sqlx v0.0.0-20180614180643-0dae4fefe7c0/go.mod h1:IiEW3SEiiErVyFdH8NTuWjSifiEQKUoyK3LNqr2kCHU=
|
||||
github.com/kolide/kit v0.0.0-20180912215818-0c28f72eb2b0 h1:8UB0NJBoB/lN2O9zG9+U2klyYE0UhvN2Zrn7HBjhwNY=
|
||||
github.com/kolide/kit v0.0.0-20180912215818-0c28f72eb2b0/go.mod h1:N3Yv8okDVC/5qZhPA9uxVYRfkp4mD2vrlQiSCWlNCpg=
|
||||
github.com/korylprince/go-cpio-odc v0.9.3 h1:MGpo1PcJN2ajysEoAhF34zR/Peevo4N+T+OmhDLIUvk=
|
||||
github.com/korylprince/go-cpio-odc v0.9.3/go.mod h1:1iHsjUXO64Hui0YsubGp0Tm/Uf04Iow2iy+1LJIarMw=
|
||||
github.com/korylprince/go-cpio-odc v0.9.4 h1:N0Afrp7Z5qCZF8cbpzF5CvyiC/KHK5IcLJwqm5MWpNU=
|
||||
github.com/korylprince/go-cpio-odc v0.9.4/go.mod h1:1iHsjUXO64Hui0YsubGp0Tm/Uf04Iow2iy+1LJIarMw=
|
||||
github.com/korylprince/go-macos-pkg v1.3.4 h1:6McQ9bj3p/k/FeqFBHhdvXVvi+ftNcWXj4EWAEuEiz0=
|
||||
github.com/korylprince/go-macos-pkg v1.3.4/go.mod h1:eLXotCZDK3vBt6AfDg62Fl20lCjrIm5e8V/8Q9YLHIo=
|
||||
github.com/korylprince/go-macos-pkg v1.3.5 h1:jwwefLR1yRKQPNu51QTwk2B4abIjjISj/BHipcvKKGs=
|
||||
github.com/korylprince/go-macos-pkg v1.3.5/go.mod h1:jlPGliXXjjCMpISR30/fL60hXKrCJ2LNQSptdx+WQkc=
|
||||
github.com/korylprince/goxar v0.0.0-20211111233330-e9f257bcdf25 h1:XVf+U+WekiGPPD27w7qI+0Pe8NehaTWPqRuO3BddefY=
|
||||
github.com/korylprince/goxar v0.0.0-20211111233330-e9f257bcdf25/go.mod h1:Lm6kfGMVHcpiBP6oOZd3ugv2EpQ/dOyW02tVIa3qo2Q=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw=
|
||||
@@ -72,18 +82,21 @@ go.mozilla.org/pkcs7 v0.0.0-20210730143726-725912489c62/go.mod h1:SNgMg+EgDFwmvS
|
||||
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 h1:CCriYyAfq1Br1aIYettdHZTy8mBTIPo7We18TuO/bak=
|
||||
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa h1:idItI2DDfCokpg0N51B2VtiLdJ4vAuXC9fnCb2gACo4=
|
||||
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/net v0.0.0-20170726083632-f5079bd7f6f7/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/sys v0.0.0-20170728174421-0f826bdd13b5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
|
||||
Reference in New Issue
Block a user