Skip to content

Commit

Permalink
certificate publisher is now recognize automatic
Browse files Browse the repository at this point in the history
  • Loading branch information
YehudaKremer committed Oct 25, 2021
1 parent f44a1ac commit d76d886
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 57 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## 2.5.0

- certificate "publisher" is now recognize automatic
- "publisher" configuration field is now deprecate
- added new flag/configuration-field "dontInstallCert"

## 2.4.2

- Documentation update
Expand Down
19 changes: 11 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ In your `pubspec.yaml`, add `msix` as a new dependency:
dev_dependencies:
flutter_test:
sdk: flutter
msix: ^2.4.2
msix: ^2.5.0
```
## :package: Create Msix
Expand All @@ -37,6 +37,14 @@ msix_config:
See [full list of available configurations](#clipboard-available-configuration-fields).
## :black_nib: Signing Options
**.msix** installer must be sign with certificate (.pfx)
- This package will automatically sign your app with build in **test certificate**.
- If you publish your app to the **Windows Store**, the app will automatically sign by the store.
- If you need to use **your own certificate**, use the configuration fields:`certificate_path, certificate_password`

**Note**: by default, this package will install the certificate on your machine, you can disable it by using the `--dontInstallCert` flag or the configuration: `dont_install_cert: true`

## ![MSIX](https://user-images.githubusercontent.com/946652/138161113-c905ec10-78f1-4d96-91ac-1295ae3d2a8c.png) Windows Store
To generate msix file for publish to the Windows Store, use the `--store` flag or add `store: true`
in msix configuration section in your `pubspec.yaml`.
Expand All @@ -47,11 +55,6 @@ you can find those values in your windows store [dashboard](https://partner.micr

For more information about publish to the Windows Store see: [How to publish your MSIX package to the Microsoft Store](https://www.advancedinstaller.com/msix-publish-microsoft-store.html)

## :black_nib: Signing Options
The created installer file (.msix) is automatically sign with default **test** certificate. for publishing, the Windows Store will automatically sign it for you.

If you need, you can use your own certificate using the configuration fields:`certificate_path, certificate_password, publisher` or `signtool_options`

## :file_folder: .dll Files And Assets (FFI Library)
To include your *.dll* and other third party assets in your msix installer, you can use the configuration field: `assets_directory_path`:
```yaml
Expand Down Expand Up @@ -90,8 +93,8 @@ Configuration Name | Description (from [microsoft docs](https://docs.microsoft.c
| architecture | Describes the architecture of the code contained in the package, one of:<br />`x86`, `x64`, `arm`, `neutral` | `x64` |
| certificate_path | Path to your certificate file | `C:/<PathToCertificate>/<MyCertificate.pfx>` |
| certificate_password | The certificate password | `1234` |
| publisher | Describes the publisher information. The Publisher attribute **must match** the publisher subject information of the certificate used to sign a package. | `CN=My Company, O=My Company, L=Berlin, S=Berlin, C=DE` |
| signtool_options | *Signtool* use the syntax: *[command] [options] [file_name]*, so you can provide here the **[options]** part, [see full documentation](https://docs.microsoft.com/en-us/dotnet/framework/tools/signtool-exe)<br /><br />this **overwriting** the fields: `certificate_path`, `certificate_password` | `/v /fd SHA256 /f C:/Users/me/Desktop/my.cer` |
| dont_install_cert | if `true`, the package won't try to install the certificate | `false` |
| file_extension | File extensions that the app will used to open | `.txt, .myFile, .test1` |
| protocol_activation | Protocol activation that will open the app | `http` |

Expand All @@ -109,7 +112,6 @@ flutter pub run msix:create --v 1.0.3.3 --c C:/Users/me/Desktop/test_certificate
- display name: `--dn`
- publisher display name: `--pdn`
- identity name: `--in`
- publisher: `--pu`
- logo path: `--lp`
- start_menu icon path: `--smip`
- tile icon path: `--tip`
Expand All @@ -126,6 +128,7 @@ flutter pub run msix:create --v 1.0.3.3 --c C:/Users/me/Desktop/test_certificate
###### Available Arguments Flags:
- store: `--store`
- debug: `--debug`
- don't install certificate: `--dontInstallCert`

---
package tags: `msi` `windows` `win10` `win11` `windows10` `windows11` `windows store` `windows installer` `windows packaging` `appx` `AppxManifest` `SignTool` `MakeAppx`
1 change: 0 additions & 1 deletion example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,4 @@ msix_config:
logo_path: C:\<PathToIcon>\<Logo.png>
certificate_path: C:\<PathToCertificate>\<MyCertificate.pfx>
certificate_password: 1234
publisher: CN=My Company, O=My Company, L=Berlin, S=Berlin, C=DE
```
5 changes: 3 additions & 2 deletions lib/msix.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@ class Msix {
assets.createIconsFolder();
assets.copyIcons();
assets.copyVCLibsFiles();
Signtool.getCertificatePublisher();
Manifest()..generateAppxManifest();
MakePri.generatePRI();
MakeAppx.pack();
assets.cleanTemporaryFiles();
if (!config.store) {
if (config.isUsingTestCertificate) {
Signtool.installTestCertificate();
if (!config.dontInstallCert) {
Signtool.installCertificate();
}
Signtool.sign();
}
Expand Down
48 changes: 42 additions & 6 deletions lib/src/cli/signtool.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,44 @@ import '../utils/log.dart';
import '../configuration.dart';

class Signtool {
static void installTestCertificate() {
const taskName = 'installing test certificate';
static void getCertificatePublisher() {
const taskName = 'getting certificate publisher';
Log.startingTask(taskName);
final config = injector.get<Configuration>();

var certificateDetails = Process.runSync('certutil',
['-dump', '-p', config.certificatePassword!, config.certificatePath!]);

const error =
'Fail to read the certificate details, please check if the certificate is valid and the password is correct';

try {
config.publisher = certificateDetails.stdout
.toString()
.split('\n')
.firstWhere((row) => row.toLowerCase().trim().startsWith('subject:'))
.replaceFirst('Subject:', '')
.replaceFirst('subject:', '')
.trim();
} catch (e) {
Log.errorAndExit(error);
}

if (certificateDetails.stderr.toString().length > 0 ||
certificateDetails.exitCode != 0) Log.errorAndExit(error);

if (certificateDetails.stderr.toString().length > 0) {
Log.error(certificateDetails.stdout);
Log.errorAndExit(certificateDetails.stderr);
} else if (certificateDetails.exitCode != 0) {
Log.errorAndExit(certificateDetails.stdout);
}

Log.taskCompleted(taskName);
}

static void installCertificate() {
const taskName = 'installing certificate';
Log.startingTask(taskName);
final config = injector.get<Configuration>();

Expand All @@ -16,19 +52,19 @@ class Signtool {

if (!installedCertificatesList.stdout
.toString()
.contains(defaultPublisher)) {
.contains(config.publisher!)) {
var isAdminCheck = Process.runSync('net', ['session']);

if (isAdminCheck.stderr.toString().contains('Access is denied')) {
Log.errorAndExit(
'to install the test certificate, you need to run this As-Admin once');
'to install the certificate "${config.certificatePath}" you need to "Run as administrator" once');
}

var result = Process.runSync('certutil', [
'-f',
'-enterprise',
'-p',
'1234',
config.certificatePassword!,
'-importpfx',
'root',
config.certificatePath!
Expand Down Expand Up @@ -101,7 +137,7 @@ class Signtool {
.toString()
.contains('Error: SignerSign() failed.') &&
!config.publisher.isNull) {
Log.printCertificateSubjectHelp();
Log.errorAndExit('signing error');
}

exit(0);
Expand Down
35 changes: 10 additions & 25 deletions lib/src/configuration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ import 'package:yaml/yaml.dart';
import 'utils/log.dart';
import 'utils/extensions.dart';

const String defaultPublisher =
'CN=Msix Testing, O=Msix Testing Corporation, S=Some-State, C=US';

class Configuration {
late ArgResults argResults;
String msixAssetsPath = '';
Expand All @@ -18,11 +15,11 @@ class Configuration {
String? assetsFolderPath;
String? msixVersion;
String? appDescription;
String? publisher;
String buildFilesFolder =
'${Directory.current.path}/build/windows/runner/Release';
String? certificatePath;
String? certificatePassword;
String? publisher;
String? displayName;
String? architecture;
String? capabilities;
Expand All @@ -36,8 +33,8 @@ class Configuration {
String? protocolActivation;
String? fileExtension;
bool debugSigning = false;
bool isUsingTestCertificate = false;
bool store = false;
bool dontInstallCert = false;
Iterable<String>? languages;
String defaultsIconsFolderPath() => '$msixAssetsPath/icons';
String vcLibsFolderPath() => '$msixAssetsPath/VCLibs';
Expand All @@ -60,6 +57,11 @@ class Configuration {
argResults.read('password') ??
config?['certificate_password']?.toString();
debugSigning = argResults.wasParsed('debug') || argResults.wasParsed('d');
dontInstallCert = argResults.wasParsed('dontInstallCert') ||
config?['dont_install_cert']?.toString().toLowerCase() == 'true';
if (dontInstallCert) {
numberOfAllTasks--;
}
store = argResults.wasParsed('store') ||
config?['store']?.toString().toLowerCase() == 'true';
if (store) {
Expand All @@ -70,7 +72,6 @@ class Configuration {
argResults.read('pdn') ?? config?['publisher_display_name']?.toString();
identityName =
argResults.read('in') ?? config?['identity_name']?.toString();
publisher = argResults.read('pu') ?? config?['publisher']?.toString();
logoPath = argResults.read('lp') ?? config?['logo_path']?.toString();
startMenuIconPath =
argResults.read('smip') ?? config?['start_menu_icon_path']?.toString();
Expand Down Expand Up @@ -178,26 +179,10 @@ class Configuration {
'Certificate password is empty, check "msix_config: certificate_password" at pubspec.yaml');
}
}

if (publisher.isNull) {
Log.error(
'Certificate subject is empty, check "msix_config: publisher" at pubspec.yaml');
if (store) {
Log.warn(
'you can find your store "publisher" in https://partner.microsoft.com/en-us/dashboard > Product > Product identity > Package/Identity/Publisher');
} else {
Log.warn('see what certificate-subject value is:');
Log.link(
'https://drive.google.com/file/d/1oAsnrp2Kf-jZ_kaRjyF5llQ0YZy1IwNe/view?usp=sharing');
}
exit(0);
}
} else {
/// If no certificate was chosen then use test certificate
certificatePath = '$msixAssetsPath/test_certificate.pfx';
certificatePassword = '1234';
publisher = defaultPublisher;
isUsingTestCertificate = true;
}

if (!['x86', 'x64'].contains(architecture)) {
Expand Down Expand Up @@ -240,7 +225,6 @@ class Configuration {
..addOption('dn') // display_name
..addOption('pdn') // publisher_display_name
..addOption('in') // identity_name
..addOption('pu') // publisher
..addOption('lp') // logo_path
..addOption('smip') // start_menu_icon_path
..addOption('tip') // tile_icon_path
Expand All @@ -253,8 +237,9 @@ class Configuration {
..addOption('a') // architecture
..addOption('cap') // capabilities
..addOption('l') // languages
..addFlag('store') // store
..addFlag('debug') // debug
..addFlag('store')
..addFlag('debug')
..addFlag('dontInstallCert')
..addFlag('d');

try {
Expand Down
15 changes: 1 addition & 14 deletions lib/src/utils/log.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import 'dart:io';
import 'package:ansicolor/ansicolor.dart';
import '../configuration.dart';

int numberOfAllTasks = 13;
int numberOfAllTasks = 14;

class Log {
static AnsiPen red = AnsiPen()..red(bold: true);
Expand Down Expand Up @@ -87,18 +86,6 @@ class Log {
}
}

/// Log `Certificate Subject` help information
static void printCertificateSubjectHelp() {
Log.warn(
'Please note: The value of Publisher should be in one line and with commas, example:');
Log.info(defaultPublisher);
Log.info('');
Log.warn('For more information see:');
Log.link(
'https://docs.microsoft.com/en-us/windows/msix/package/create-certificate-package-signing#determine-the-subject-of-your-packaged-app');
Log.info('');
}

static String _getlastMessageEmptyStringLength() {
var emptyStr = '';
for (var i = 0; i < lastMessageLength + 8; i++) {
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: msix
description: A command-line tool that create Msix installer from your flutter windows-build files.
version: 2.4.2
version: 2.5.0
maintainer: Yehuda Kremer (yehudakremer@gmail.com)
homepage: https://github.com/YehudaKremer/msix

Expand Down

0 comments on commit d76d886

Please sign in to comment.