Draft `App Sandbox and Entitlements`

sethlu 2016-02-24 07:56:52 +08:00
Родитель b998311a1b
Коммит b1ec67dbac
4 изменённых файлов: 112 добавлений и 87 удалений

@ -0,0 +1,111 @@
All apps that are submitted for distribution inside the Mac App Store must run inside a "sandbox." This basically means that every sandboxed apps will run under a limited set of permissions, and damages from malicious code, if any, could be minimized. If your application requires additional capabilities, it then must include in its *entitlements* the corresponding *entitlement keys*, which are specified during the code signing process. The entitlement keys mark capabilities and/or permissions that are needed by the application.
*Note: The App Sandbox basically means code-signing your app with entitlements, and specifically the sandbox entitlement key enabled.*
A list of [App Sandbox entitlement keys](https://developer.apple.com/library/mac/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html) and their definitions can be found on Apple Developer. You may notice that a sandbox app does not have full-access to every aspect of the machine. For example you cannot read/write to any location on the machine; your app is limited to specific folders such as Downloads, Music, Pictures, etc. So additionally, there are [temporary exception entitlement keys](https://developer.apple.com/library/mac/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/AppSandboxTemporaryExceptionEntitlements.html) available that allow your apps to perform certain operations otherwise disallowed by the App Sandbox, and to access files outside of these areas in this case. Temporary exceptions come with their own requirements, for example the user must specifically select a location with an Open File dialog. Your app may then have temporary permission to that location.
*Note: It's unnecessary to add temporary exceptions for temporary directories in OS X, like `/tmp`
Entitlements are specified using a `.entitlements` file with format like property list (`.plist`) or XML. You must provide an entitlement file for the application bundle itself and a child entitlement file which basically describes an inheritance of properties, specified for all other enclosing executable files like binaries, frameworks (`.framework`), and dynamically linked libraries (`.dylib`).
*Note: It's worth mentioning that wildcard expressions with asterisks are generally not accepted by `codesign`. Also, the entitlement files have size limits. So it's not at all recommended to throw in every possible cases, populating the file to several megabytes, which will throw errors when code-signing. Keep it as brief as possible.*
#### Extend the Entitlements
With `electron-osx-sign`, it is unnecessary to manually prepare those entitlement files unless for specific purposes. The entitlements for signing the application bundle by default are defined in [`mas.default.entitlements`](https://github.com/sethlu/electron-osx-sign/blob/master/mas.default.entitlements); and for the enclosing executable files, in [`mas.inherit.default.entitlements`](https://github.com/sethlu/electron-osx-sign/blob/master/mas.inherit.default.entitlements).
Below is `mas.default.entitlements`. The easiest way to add entitlements is to edit a copy and to simply customize the plist by adding your additional entitlements.
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
</dict>
</plist>
```
Below is `mas.inherit.default.entitlements`. You can generally leave this file as-is because all of the enclosing files will inherit whatever entitlements that are specified in the entitlements for the application bundle, `mas.default.entitlements`. (This is done with the key `com.apple.security.inherit` set to `true`.)
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.inherit</key>
<true/>
</dict>
</plist>
```
##### Customize Entitlements
The following example is a plist for an app that will read from/write to the "Downloads" folder as well as make network requests to external servers. Notice that it simply provides an additional "key" for each of these capabilities. For example, `com.apple.security.files.downloads.read-write` specifies permission to read/write to the user's downloads folder and `com.apple.security.network.client` specifies permission to make network requests.
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.files.downloads.read-write</key>
<true/>
</dict>
</plist>
```
Please also make note that some entitlement keys may require value type `array`, instead of boolean values. For example, `com.apple.security.temporary-exception.files.absolute-path.read-write`, which enables read/write access to the specified files or directories at specified absolute paths, should be done as follows if to access any directories. *This act is not recommended as we should minimize what the sandboxed apps touch in the system, and may probably result in rejection from submission.*
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.temporary-exception.files.absolute-path.read-write</key>
<array>
<string>/</string>
</array>
</dict>
</plist>
```
*Note: You can always append more than just one `<string>` within the `<array>` container.*
#### What A Sandboxed App Could Access Anyway
Though sandboxed, the apps can touch some parts of the system without specifying additional entitlements. They could read files that are world readable, in certain directories, including the following:
* `/bin`
* `/sbin`
* `/usr/bin`
* `/usr/lib`
* `/usr/sbin`
* `/usr/share`
* `/System`
Also, they could read/write files in directories created for temporary use.
#### Apply the Entitlements
If you have any custom entitlements, please specify `entitlements` and/or `entitlements-inherit` when code-signing with `electron-osx-sign`. On the other hand, if you are using `electron-packager` and would like to sign with entitlements directly from it, the `sign-entitlements` option is also available for use.
```sh
# EITHER pack your app and sign it all at once
electron-packager . "My App" --platform=mas --arch=x64 --version=0.35.6 --app-bundle-id="com.mysite.myapp" --app-version="1.0.0" --build-version="1.0.100" --sign --sign-entitlements="path/to/parent.entitlements"
# OR pack your app first then manually sign it
electron-packager . "My App" --platform=mas --arch=x64 --version=0.35.6 --app-bundle-id="com.mysite.myapp" --app-version="1.0.0" --build-version="1.0.100"
# code-sign app bundle with custom entitlements
electron-osx-sign "My App-mas-x64/My App.app" --entitlements="path/to/parent.entitlements" --entitlements-inherit="path/to/child.entitlements"
```
*Note: `electron-osx-sign` will take care of all enclosing executables under `My App.app/Contents/Frameworks`. If there are other binaries that do not come with Electron under `My App.app/Contents/Resources` that you would like to be signed as well, provide them in `additional-binaries`.*

@ -1,77 +0,0 @@
#### About Entitlements
All apps that are submitted to the Mac App Store must run inside the "App Sandbox." This basically means that the app runs with a limited set of permissions. If your application requires additional capabilities, it must include a list of *entitlements*, which are specified during the code signing process. Entitlements are simply capabilities and/or permissions that are needed by the application. Entitlements include things such as read/write permission to files outside of the application directory, network connectivity or direct access to hardware such as the camera. A [full list of entitlements](https://developer.apple.com/library/mac/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html#//apple_ref/doc/uid/TP40011195-CH4-SW1) can be found on the Apple developer documentation site.
Entitlements are specified using a specially formatted plist (XML) file that is provided when you sign your application. You must provide an entitlement file for each binary or framework within your app bundle, and a separate entitlement file for the app bundle itself. (The app bundle uses the "default" entitlement file and the binaries inside it use the "inherited" entitlement file).
#### Specifying An Entitlement File
When using electron-osx-sign to sign your app, by default two entitlement files are used which do not specify any permissions beyond those of the default sandbox. You can find these two files in the root of the `electron-osx-sign` installation folder nameed `mas.default.plist` and `mas.inherit.default.plist`.
If you require additional permissions then you must provide a path to your own custom entitlement files as arguments, for example:
```
electron-osx-sign "$APP_PATH" --entitlements=path/to/my.default.plist --entitlements-inherit=path/to/my.inherited.plist --verbose
```
#### The Default 'mas.default.plist' file:
This is the file that is used by `electron-osx-sign` by default. The easiest way to add entitlements is to simply customize this file by adding your additional entitlements.
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
</dict>
</plist>
```
#### The Default 'mas.inherited.default.plist' file:
This is the default inherited file. You can generally leave this file as-is because all of the binaries signed with this file will inherit whatever entitlements were specified in the default file. (This is because it has a key "com.apple.security.inherit" with a value of <true/>)
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.inherit</key>
<true/>
</dict>
</plist>
```
#### A Custom Entitlement File Example:
The following example is a plist for an app that will write to the "Downloads" folder as well as make network requests to external servers. Notice that it simply provides an additional "key" for each of these capabilities. For example "com.apple.security.files.downloads.read-write" specifies permission to read/write to the user's downloads folder and "com.apple.security.network.client" specifies permission to make network requests.
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.app-sandbox</key>
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.files.downloads.read-write</key>
<true/>
</dict>
</plist>
```
If you refer to the [full list of entitlements](https://developer.apple.com/library/mac/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html#//apple_ref/doc/uid/TP40011195-CH4-SW1) you can find the "keys" for all of the permissions that are available to your app.
Simply add as many of these entitlements to the plist file as is require by your app. Follow the key/value format of the two entitlements in this example.
You may notice that a sandbox app does not have full-access to every aspect of the machine. For example you cannot read/write to any location on the machine. Your app is limited to specific folders such as Downloads, Music, Pictures, etc. There are additional [Temporary Entitlement Exceptions](https://developer.apple.com/library/mac/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/AppSandboxTemporaryExceptionEntitlements.html#//apple_ref/doc/uid/TP40011195-CH5-SW1) that allow you to access files outside of these areas. Temporary exceptions come with their own requirements, for example the user must specifically select a location with an Open File dialog. You app may then have temporary permission to that location.
If your app attempts to access a feature or permission for which you have not specified entitlements, then the operating system will block the operation and your app will throw an error or crash. However you will not see these errors in your debug build, so it is important that you test your applications production MAS build before submitting it to the App Store.
Good Luck!
---

@ -4,11 +4,10 @@ Welcome to the electron-osx-sign wiki!
1. [Getting Started](https://github.com/sethlu/electron-osx-sign/wiki/1.-Getting-Started)
2. [Electron Compatibility](https://github.com/sethlu/electron-osx-sign/wiki/2.-Electron-Compatibility)
3. App Sandboxing and Entitlements
3. [App Sandbox and Entitlements](https://github.com/sethlu/electron-osx-sign/wiki/3.-App-Sandbox-and-Entitlements)
4. Application Packaging
5. Shipping your Binary
#### Drafting Articles
* [Packaging and Submitting an Electron App to the Mac App Store](https://github.com/sethlu/electron-osx-sign/wiki/Packaging-and-Submitting-an-Electron-App-to-the-Mac-App-Store)
* [Entitlement Files for Mac App Store](https://github.com/sethlu/electron-osx-sign/wiki/Entitlement-Files-for-Mac-App-Store)

@ -37,14 +37,6 @@ If your app includes any additional binary files (command-line applications for
electron-osx-sign "My App-mas-x64/My App.app" "My App-mas-x64/My App.app/Contents/Resources/app/bin/mybinary" --verbose
```
###### If you have any custom entitlements:
If your app requires any custom entitlements such as file access, network access, etc then you must create your own parent.plist and child.plist entitlement files. You then specify the path to those plist files. The "parent" is the entitlement used to sign the entire app bundle. The "child" is the entitlement used to sign the frameworks and binaries inside the bundle. Additional information about entitlements and the plist files is available on the page [Entitlement Files for Mac App Store](https://github.com/sethlu/electron-osx-sign/wiki/Entitlement-Files-for-Mac-App-Store).
```
electron-osx-sign "My App-mas-x64/My App.app" --entitlements=path/to/parent.plist --entitlements-inherit=path/to/child.plist --verbose
```
###### If you have multiple developer identities in your keychain:
electron-osx-sign searches your keychain for the first signing certificates that it can locate. If you have multiple certificates then it may not know which cert you want to use for signing and you need to explicitly provide the name: