1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
|
// Copyright (C) 2021 The Qt Company Ltd.
// Copyright (C) 2019 Luxoft Sweden AB
// Copyright (C) 2018 Pelagicore AG
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
/*!
\page installer.html
\ingroup qtappman
\title Package Installation
\brief Discusses the package installation infrastructure.
\keyword Installer
\section1 Dynamically Installing, Updating, and Removing Packages
After applications have been packaged by the \l {Packager}{\c appman-packager} tool, they can be
installed by the application manager at runtime. There are two interfaces for this functionality:
\list
\li A QML interface for use within the application manager process.
\li A D-Bus interface for use by any process that is allowed to talk to the application
manager's \c PackageManager interface.
\endlist
Both interfaces are very similar and are described in the PackageManager.
\note A prerequisite for dynamically installed application packages is a valid
\l {Configuration}{\c installationDir configuration} for the application manager.
\section1 Packages
The application manager has its own \l {Package Format}. It comes with the \l {Packager}{\c
appman-packager} command-line tool, for you to create and verify those packages.
\section1 Installation Sources
When triggering a package installation, you have to provide a URL to the application manager as
the source of the package. Out of the box, the application manager accepts the following schemes:
\table
\header
\li Scheme
\li Description
\row
\li \c file://
\li A local filesystem path.
\row
\li \c http://, \c https:// and \c ftp://
\li A remote path that is downloaded via QNetworkAccessManager.
\row
\li \c socket://
\li A path to a UNIX-domain socket in the local filesystem. This is very useful for streaming in
packages, if you do not want to (or can) use the built-in downloader, or if your packages are
wrapped inside another customer-specific distribution file format.
\endtable
All of the above methods work asynchronously and also support streaming: this means that the actual
installation is done while the package is being downloaded. If the package is successfully verified
after the download, it only needs a quick finalization step. Otherwise, if an error occurred, the
installation process is simply canceled and rolled back.
\section1 Public Key Infrastructure
To use signed packages, you require a Public Key Infrastructure (PKI) to support this, which means
that you need two Certificate Authorities (CAs):
\list
\li A \e {Developer CA}: responsible for creating certificates that are distributed to developers
in P12 format. The developers use these certificates to developer-sign their packages, using
the \l {Packager}, before submitting to an app store.
\li An \e {App-Store CA}: responsible for creating certificates for use by app store server
back ends to store-sign packages, before they are downloaded and installed onto devices.
\endlist
Both these CAs can be the same or they can be derived from a common root CA.
For the device, you need to install one or both of these CA certificates, including any root or
intermediary ones. But, this depends on the type of package you want the user to be able to
install. Which CA certificates to load is specified via \l {ca certificates} {the config file}.
The application manager sources have a script,
\c tests/data/certificates/create-test-certificates.sh, that sets up such a PKI for the internal
unit tests. This script is \b not for use in production, but only for use in developing with
signed packages.
New in 6.11:
\list
\li Developer certificates can be bound to one or more specific package IDs, to prevent shadowing
or replacement of packages that are not owned by the developer. See \l {Binding Developer
Certificates to Package IDs}{below} for more information.
\li Developer certificates need to have the \c decipherOnly bit set in the \e{Key Usage} X509
extension, while App-Store certificates need to have the \c encipherOnly bit set. This ensures
that developer and app-store certificates cannot be used interchangeably. The X509 format is not
easily extensible, but these otherwise unused key-usage bits can easily be set in any tool used
for creating certificates.
\li The fingerprints of issuer certificates can optionally be white-listed in the configuration file.
\li Certificate Revocation Lists (CRLs) can be loaded to revoke developer or app-store certificates.
\endlist
\section2 Creating Developer Certificates
The examples below use the \c{openssl} command-line tool to create keys, CSRs, and certificates.
You are however free to use any other tool that is able to create X.509v3 and PKCS#12 certificates.
For a developer to receive a developer certificate, they would typically generate a private key and
a certificate signing request (CSR) for their package:
\badcode
$ openssl req -new -nodes -newkey rsa:2048 -subj "/CN=Developer 1" \
-addext "subjectAltName=URI:qtam://packageid/my-package-id" \
-keyout developer.key -out developer-req.csr
\endcode
Please note that the actual parameters like key size and subject name would depend on your PKI
policy. In this example, a 2048-bit RSA key is created with the common name \e "Developer 1".
The \c{subjectAltName} extension is used to bind the developer certificate to one or more specific
package IDs, in this case \c my-package-id.
See \l{Binding Developer Certificates to Package IDs}{below for more information}.
The \c developer-req.csr file would then be sent to the Developer CA for signing, while the
\c developer.key file is kept private by the developer.
On the CA side, the CSR is then verified and signed to create the developer certificate. Please
note that developer certificates need to have the \c decipherOnly bit set in the \e{Key Usage}
X509 extension.
\badcode
$ openssl ca -batch -config dev-ca.conf -policy signing_policy -extensions signing_req \
-out developer.crt -infiles developer-req.csr
\endcode
This generates the signed \c developer.crt file, which is then sent back to the developer.
The final step for developers is to bundle their private key and the signed certificate into a
P12 file, which is the format that the \l {Packager}{\c appman-packager} tool expects:
\badcode
$ openssl pkcs12 -export -out developer.p12 -in developer.crt -inkey developer.key
\endcode
\section2 Binding Developer Certificates to Package IDs
Up to version 6.11, all developer certificates were treated equally, meaning that a developer
could sign any package. From version 6.11 onwards, developer certificates can be
bound to one or more specific package IDs, to prevent shadowing or replacement of packages
that are not owned by the developer.
This ID list is stored in the \c{subjectAltName} X.509v3 extension of the developer certificate as
\c {URI:qtam://packageid/...} entries. This extension is conventionally used to store alternative
domain names for HTTPS server certificates.
As with HTTPS certificates, you can use the \c{*} wildcard character to match multiple package
IDs. For example, a developer certificate with the following \c{subjectAltName} extension:
\badcode
subjectAltName = URI:qtam://packageid/com.vendor.*, URI:qtam://packageid/io.qt.example
\endcode
would allow the developer to create and sign packages with an ID starting with
\c{com.vendor.}, as well as the specific package with the ID \c{io.qt.example}.
\note Adding this information is \b optional for developer certificates to retain backwards
compatibility. However you are highly encouraged to add this information to your developer
certificates to improve security. If you still need to issue an unrestricted developer certificate,
you can use \c{URI:qtam://packageid/*} to explicitly allow all package IDs.
\section2 Developer Signing Packages
Each package can only have exactly one developer signature.
A developer would sign their package as follows, after obtaining a valid developer certificate in
P12 format (see above).
\badcode
$ appman-packager dev-sign-package the-pkg.ampkg the-pkg.dev-signed.ampkg developer.p12
\endcode
This takes the input package \c the-pkg.ampkg, signs it with the \c developer.p12 signature, and
writes the output to \c the-pkg.dev-signed.ampkg.
The signed package would then be uploaded/sent to an app-store for further processing.
\section2 Store Signing Packages
Each package can only have exactly one app-store signature.
When a developer submits a package to an app-store, the app-store server backend and/or a human
tester would verify the \e developer signature on the package first:
\badcode
$ appman-packager dev-verify-package --verbose the-pkg.dev-signed.ampkg dev-ca.crt intermediate-ca.crt root-ca.crt
\endcode
The actual number and names of the requires CA certificates depends on your PKI setup. The above
is just an example.
Next, the contents of the package should be verified: first and foremost the contents of \c
info.yaml, but also the actual application code.
Finally the package is signed with a \e store key:
\badcode
$ appman-packager store-sign-package the-pkg.signed.ampkg the.pkg.dev-store-signed.ampkg store.p12
\endcode
This takes the input package \c the-pkg.dev-signed.ampkg, signs it with the \c store.p12 signature,
and writes the output to \c the-pkg.dev-store-signed.ampkg.
The store-signed package would then be made available for download and installation.
In order to differentiate between developer and store certificates (even if you use the same CA for
everything), store certificates need to have the \c encipherOnly bit set in the \e{Key Usage} X509
extension.
\section1 Related Content
\list
\li \l {Package Format}
\li \l {Packager}
\li \l {PackageManager}{PackageManager API}
\endlist
*/
|