Skip to content

Commit

Permalink
Merge pull request #119 from grahamgilbert/auth_mechs
Browse files Browse the repository at this point in the history
Manage Auth Mechs
  • Loading branch information
grahamgilbert authored Feb 26, 2024
2 parents 1c77a2f + f7caf66 commit 612593d
Show file tree
Hide file tree
Showing 11 changed files with 273 additions and 23 deletions.
2 changes: 1 addition & 1 deletion Crypt/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>257</string>
<string>262</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2024 The Crypt Project. All rights reserved.</string>
<key>NSPrincipalClass</key>
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ build_binary:
# bazel build --platforms=@io_bazel_rules_go//go/toolchain:darwin_amd64 //:cmd:crypt-amd
# bazel build --platforms=@io_bazel_rules_go//go/toolchain:darwin_arm //cmd:crypt-arm
# tools/bazel_to_builddir.sh
CGO_ENABLED=1 CC=/opt/homebrew/opt/llvm/bin/clang CXX=/opt/homebrew/opt/llvm/bin/clang++ GOOS=darwin GOARCH=arm64 go build -ldflags "-X main.version=${PACKAGE_VERSION}" -o build/checkin.arm64 cmd/main.go
CGO_ENABLED=1 CC=/opt/homebrew/opt/llvm/bin/clang CXX=/opt/homebrew/opt/llvm/bin/clang++ GOOS=darwin GOARCH=amd64 go build -ldflags "-X main.version=${PACKAGE_VERSION}" -o build/checkin.amd64 cmd/main.go
CGO_ENABLED=1 CC=/opt/homebrew/opt/llvm/bin/clang CXX=/opt/homebrew/opt/llvm/bin/clang++ GOOS=darwin GOARCH=arm64 go build -ldflags "-X main.version=${BUNDLE_VERSION}" -o build/checkin.arm64 cmd/main.go
CGO_ENABLED=1 CC=/opt/homebrew/opt/llvm/bin/clang CXX=/opt/homebrew/opt/llvm/bin/clang++ GOOS=darwin GOARCH=amd64 go build -ldflags "-X main.version=${BUNDLE_VERSION}" -o build/checkin.amd64 cmd/main.go
/usr/bin/lipo -create -output build/checkin build/checkin.arm64 build/checkin.amd64
/bin/rm build/checkin.arm64
/bin/rm build/checkin.amd64
Expand Down
22 changes: 14 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@

**WARNING:** As this has the potential for stopping users from logging in, extensive testing should take place before deploying into production.

Crypt is an authorization plugin that will enforce FileVault 2, and then submit it to an instance of [Crypt Server](https://github.com/grahamgilbert/crypt-server). Crypt supports macOS 11 and 12. For versions below 11.0, please use version 4.0.0. For versions below 10.12 please use version 2 and below.

Version 3.0.0 now supports 10.12 and above, previous macOS version support has been deprecated!
Crypt is an authorization plugin that will enforce FileVault 2, and then submit it to an instance of [Crypt Server](https://github.com/grahamgilbert/crypt-server). Crypt supports macOS 13 and above. For versions below 13.0, please use version 4.1.0. For versions below 11.0, please use version 4.0.0. For versions below 10.12 please use version 2 and below.

When using Crypt with macOS 10.15 and higher, you will also need to deploy a PPC TCC profile via user approved MDM to allow Crypt to enable FileVault. [An example can be found here.](https://github.com/grahamgilbert/crypt/blob/master/ppctcc_example.mobileconfig)

Expand All @@ -26,6 +24,14 @@ The `ServerURL` preference sets your Crypt Server. Crypt will not enforce FileVa
$ sudo defaults write /Library/Preferences/com.grahamgilbert.crypt ServerURL "https://crypt.example.com"
```

### ManageAuthMechs

By default, Crypt will ensure the Authenication Mechaniss are set up correctly. If you want to disable this, you can set the `ManageAuthMechs` preference to `FALSE`.

```bash
$ sudo defaults write /Library/Preferences/com.grahamgilbert.crypt ManageAuthMechs -bool FALSE
```

### SkipUsers

The `SkipUsers` preference allows you to define an array of users that will not be forced to enable FileVault.
Expand Down Expand Up @@ -54,23 +60,23 @@ For macOS 10.15 and above, you may want to use the `ROTATE_VIEWED_SECRETS` key i

### ValidateKey

Crypt2 can validate the recovery key if it is stored on disk. If the key fails validation, the plist is removed so it can be regenerated on next login. This is set to `TRUE` by default.
Crypt can validate the recovery key if it is stored on disk. If the key fails validation, the plist is removed so it can be regenerated on next login. This is set to `TRUE` by default.

```bash
$ sudo defaults write /Library/Preferences/com.grahamgilbert.crypt ValidateKey -bool FALSE
```

### OutputPath

As of version 3.0.0 you can now define a new location for where the recovery key is written to. Default for this is `'/var/root/crypt_output.plist'`.
You can define a new location for where the recovery key is written to. Default for this is `'/var/root/crypt_output.plist'`.

```bash
$ sudo defaults write /Library/Preferences/com.grahamgilbert.crypt OutputPath "/path/to/different/location"
```

### KeyEscrowInterval

As of version 3.0.0 you can now define the time interval in Hours for how often Crypt tries to re-escrow the key, after the first successful escrow. Default for this is `1` hour.
You can define the time interval in Hours for how often Crypt tries to re-escrow the key, after the first successful escrow. Default for this is `1` hour.

```bash
$ sudo defaults write /Library/Preferences/com.grahamgilbert.crypt KeyEscrowInterval -int 2
Expand All @@ -86,7 +92,7 @@ $ sudo defaults write /Library/Preferences/com.grahamgilbert.crypt AdditionalCur

### PostRunCommand

(Introduced in version 3.2.0) This is a command that is run after Crypt has detected an error condition with a stored key that cannot be resolved silently - either it has failed validation or the server has instructed the client to rotate the key. These cannot be resolved silently on APFS volumes, so the user will need to log in again. If you have a tool that can enforce a logout or a reboot, you can run it here. This preference can either be a string if your command has no spaces, or an array if there are spaces in the command.
This is a command that is run after Crypt has detected an error condition with a stored key that cannot be resolved silently - either it has failed validation or the server has instructed the client to rotate the key. These cannot be resolved silently on APFS volumes, so the user will need to log in again. If you have a tool that can enforce a logout or a reboot, you can run it here. This preference can either be a string if your command has no spaces, or an array if there are spaces in the command.

## Uninstalling

Expand All @@ -102,4 +108,4 @@ You will need to configure Xcode 9.3 (requires 10.13.2 or later) to sign the bun

## Credits

Crypt 2 couldn't have been written without the help of [Tom Burgin](https://github.com/tburgin) - he is responsible for all of the good code in this project. The bad bits are mine.
Crypt couldn't have been written without the help of [Tom Burgin](https://github.com/tburgin) - he is responsible for all of the good code in this project. The bad bits are mine.
2 changes: 1 addition & 1 deletion cmd/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ go_library(
importpath = "github.com/grahamgilbert/crypt/cmd",
visibility = ["//visibility:private"],
deps = [
"//pkg/authmechs:postinstall",
"//pkg/checkin",
"//pkg/postinstall",
"//pkg/pref",
"//pkg/utils",
],
Expand Down
13 changes: 10 additions & 3 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"log"
"os"

"github.com/grahamgilbert/crypt/pkg/authmechs"
"github.com/grahamgilbert/crypt/pkg/checkin"
"github.com/grahamgilbert/crypt/pkg/postinstall"
"github.com/grahamgilbert/crypt/pkg/pref"
"github.com/grahamgilbert/crypt/pkg/utils"
)
Expand All @@ -18,6 +18,7 @@ func main() {

install := flag.Bool("install", false, "Install the AuthDB mechanisms")
uninstall := flag.Bool("uninstall", false, "Uninstall the AuthDB mechanisms")
checkMechs := flag.Bool("check-auth-mechs", false, "Check the AuthDB mechanisms. Returns 0 if all are present, 1 if not.")
versionFlag := flag.Bool("version", false, "print the version")
flag.Parse()

Expand All @@ -28,13 +29,19 @@ func main() {
os.Exit(0)
}
if *install {
err := postinstall.Run(r, true)
err := authmechs.Run(r, true)
if err != nil {
log.Println(err)
os.Exit(1)
}
} else if *uninstall {
err := postinstall.Run(r, false)
err := authmechs.Run(r, false)
if err != nil {
log.Println(err)
os.Exit(1)
}
} else if *checkMechs {
err := authmechs.Check(r)
if err != nil {
log.Println(err)
os.Exit(1)
Expand Down
14 changes: 12 additions & 2 deletions pkg/postinstall/BUILD.bazel → pkg/authmechs/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")

go_library(
name = "postinstall",
srcs = ["postinstall.go"],
importpath = "github.com/grahamgilbert/crypt/pkg/postinstall",
srcs = ["authemechs.go"],
importpath = "github.com/grahamgilbert/crypt/pkg/authmechs",
visibility = ["//visibility:public"],
deps = [
"//pkg/utils",
Expand All @@ -17,3 +17,13 @@ go_test(
embed = [":postinstall"],
deps = ["@com_github_stretchr_testify//assert"],
)

go_test(
name = "authmechs_test",
srcs = ["authmechs_test.go"],
embed = [":authmechs"],
deps = [
"//pkg/utils",
"@com_github_stretchr_testify//assert",
],
)
64 changes: 59 additions & 5 deletions pkg/postinstall/postinstall.go → pkg/authmechs/authemechs.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package postinstall
package authmechs

import (
"errors"
"fmt"
"log"
"os"
"reflect"

"github.com/grahamgilbert/crypt/pkg/utils"
"github.com/groob/plist"
Expand Down Expand Up @@ -37,6 +40,19 @@ func removeMechsInDB(db AuthDB, mechList []string) AuthDB {
return db
}

func checkMechsInDB(db AuthDB, mechList []string, indexMech string, indexOffset int) bool {
insertIndex := indexOf(db.Mechanisms, indexMech) - len(mechList) // start from the position before the indexMech

// Check if the position is valid
if insertIndex < 0 || insertIndex+len(mechList) > len(db.Mechanisms) {
fmt.Println("Invalid index")
return false
}

// Compare the corresponding elements of the two slices
return reflect.DeepEqual(db.Mechanisms[insertIndex:insertIndex+len(mechList)], mechList)
}

func setMechsInDB(db AuthDB, mechList []string, indexMech string, indexOffset int, add bool) AuthDB {
db = removeMechsInDB(db, mechList)

Expand Down Expand Up @@ -75,14 +91,23 @@ func indexOf(slice []string, item string) int {
return -1
}

func editAuthDB(r utils.Runner, add bool) error {
func getAuthDb(r utils.Runner) (AuthDB, error) {
securityConsoleOut, err := r.Runner.RunCmd("/usr/bin/security", "authorizationdb", "read", "system.login.console")
if err != nil {
return err
return AuthDB{}, err
}

var d AuthDB
err = plist.Unmarshal(securityConsoleOut, &d)
if err != nil {
return AuthDB{}, err
}

return d, nil
}

func editAuthDB(r utils.Runner, add bool) error {
d, err := getAuthDb(r)
if err != nil {
return err
}
Expand All @@ -109,15 +134,44 @@ func checkRoot() error {
return nil
}

func Run(r utils.Runner, add bool) error {
func Check(r utils.Runner) error {
err := checkRoot()
if err != nil {
return err
}
err = editAuthDB(r, add)

d, err := getAuthDb(r)
if err != nil {
return err
}

if !checkMechsInDB(d, fv2Mechs, fv2IndexMech, fv2IndexOffset) {
return errors.New("mechanisms are not set correctly")
}

return nil
}

func Run(r utils.Runner, add bool) error {
err := checkRoot()
if err != nil {
return err
}

return editAuthDB(r, add)
}

func Ensure(r utils.Runner) error {
d, err := getAuthDb(r)
if err != nil {
return err
}

if checkMechsInDB(d, fv2Mechs, fv2IndexMech, fv2IndexOffset) {
return nil
}

log.Println("Mechanisms are not set correctly, adding to AuthDB")

return editAuthDB(r, true)
}
Loading

0 comments on commit 612593d

Please sign in to comment.