github.com/rkt/rkt@v1.30.1-0.20200224141603-171c416fac02/Documentation/signing-and-verification-guide.md (about) 1 # Signing and Verification Guide 2 3 This guide will walk you through signing, distributing, and verifying the hello ACI created in the [getting started guide][getting-started]. 4 5 ``` 6 hello-0.0.1-linux-amd64.aci 7 ``` 8 9 * [Signing ACIs](#signing-acis) 10 * [Distributing Images via Meta Discovery](#distributing-images-via-meta-discovery) 11 * [Verifying Images with rkt](#verifying-images-with-rkt) 12 * [Establishing Trust](#establishing-trust) 13 * [Example Usage](#example-usage) 14 15 ## Signing ACIs 16 17 By default rkt requires ACIs to be signed using a gpg detached signature. 18 The following steps will walk you through the creation of a gpg keypair suitable for signing an ACI. 19 If you have an existing gpg signing key skip to the [Signing the ACI](#signing-the-aci) step. 20 21 ### Generate a gpg signing key 22 23 Create a file named `gpg-batch` with the following contents: 24 25 ``` 26 %echo Generating a default key 27 Key-Type: RSA 28 Key-Length: 2048 29 Subkey-Type: RSA 30 Subkey-Length: 2048 31 Name-Real: Carly Container 32 Name-Comment: ACI signing key 33 Name-Email: carly@example.com 34 Expire-Date: 0 35 Passphrase: rkt 36 %pubring rkt.pub 37 %secring rkt.sec 38 %commit 39 %echo done 40 ``` 41 42 #### Generate the key using batch mode 43 44 ``` 45 $ gpg --batch --gen-key gpg-batch 46 ``` 47 48 #### List the keys 49 50 ``` 51 $ gpg --no-default-keyring \ 52 --secret-keyring ./rkt.sec --keyring ./rkt.pub --list-keys 53 ./rkt.pub 54 ------------ 55 pub 2048R/26EF7A14 2015-01-09 56 uid [ unknown] Carly Container (ACI signing key) <carly@example.com> 57 sub 2048R/B9C074CD 2015-01-09 58 ``` 59 60 From the output above the level of trust for the signing key is unknown. 61 This will cause the following warning if we attempt to validate an ACI signed with this key using the gpg cli: 62 63 ``` 64 gpg: WARNING: This key is not certified with a trusted signature! 65 ``` 66 67 Since we know exactly where this key came from let's trust it: 68 69 ``` 70 $ gpg --no-default-keyring \ 71 --secret-keyring ./rkt.sec \ 72 --keyring ./rkt.pub \ 73 --edit-key 26EF7A14 \ 74 trust 75 gpg (GnuPG/MacGPG2) 2.0.22; Copyright (C) 2013 Free Software Foundation, Inc. 76 This is free software: you are free to change and redistribute it. 77 There is NO WARRANTY, to the extent permitted by law. 78 79 Secret key is available. 80 81 pub 2048R/26EF7A14 created: 2015-01-09 expires: never usage: SC 82 trust: unknown validity: unknown 83 sub 2048R/B9C074CD created: 2015-01-09 expires: never usage: E 84 [ unknown] (1). Carly Container (ACI signing key) <carly@example.com> 85 86 Please decide how far you trust this user to correctly verify other users' keys 87 (by looking at passports, checking fingerprints from different sources, etc.) 88 89 1 = I don't know or won't say 90 2 = I do NOT trust 91 3 = I trust marginally 92 4 = I trust fully 93 5 = I trust ultimately 94 m = back to the main menu 95 96 Your decision? 5 97 Do you really want to set this key to ultimate trust? (y/N) y 98 99 pub 2048R/26EF7A14 created: 2015-01-09 expires: never usage: SC 100 trust: ultimate validity: unknown 101 sub 2048R/B9C074CD created: 2015-01-09 expires: never usage: E 102 [ unknown] (1). Carly Container (ACI signing key) <carly@example.com> 103 Please note that the shown key validity is not necessarily correct 104 unless you restart the program. 105 106 gpg> quit 107 ``` 108 109 #### Export the public key 110 111 ``` 112 $ gpg --no-default-keyring --armor \ 113 --secret-keyring ./rkt.sec --keyring ./rkt.pub \ 114 --export carly@example.com > pubkeys.gpg 115 ``` 116 117 ### Signing the ACI 118 119 ``` 120 $ gpg --no-default-keyring --armor \ 121 --secret-keyring ./rkt.sec --keyring ./rkt.pub \ 122 --output hello-0.0.1-linux-amd64.aci.asc \ 123 --detach-sig hello-0.0.1-linux-amd64.aci 124 ``` 125 126 #### Verify the image using gpg 127 128 ``` 129 $ gpg --no-default-keyring \ 130 --secret-keyring ./rkt.sec --keyring ./rkt.pub \ 131 --verify hello-0.0.1-linux-amd64.aci.asc hello-0.0.1-linux-amd64.aci 132 gpg: Signature made Fri Jan 9 05:01:49 2015 PST using RSA key ID 26EF7A14 133 gpg: Good signature from "Carly Container (ACI signing key) <carly@example.com>" [ultimate] 134 ``` 135 136 At this point you should have the following three files: 137 138 ``` 139 hello-0.0.1-linux-amd64.aci.asc 140 hello-0.0.1-linux-amd64.aci 141 pubkeys.gpg 142 ``` 143 144 ## Distributing Images via Meta Discovery 145 146 Host `example.com/hello` with the following HTML contents and meta tags: 147 148 ```html 149 <!DOCTYPE html> 150 <html lang="en"> 151 <head> 152 <meta charset="utf-8"> 153 <meta name="ac-discovery" content="example.com/hello https://example.com/images/{name}-{version}-{os}-{arch}.{ext}"> 154 <meta name="ac-discovery-pubkeys" content="example.com/hello https://example.com/pubkeys.gpg"> 155 </head> 156 </html> 157 ``` 158 159 Serve the following files at the locations described in the meta tags: 160 161 ``` 162 https://example.com/images/example.com/hello-0.0.1-linux-amd64.aci.asc 163 https://example.com/images/example.com/hello-0.0.1-linux-amd64.aci 164 https://example.com/pubkeys.gpg 165 ``` 166 167 ### rkt Integration 168 169 Let's walk through the steps rkt takes when fetching images using Meta Discovery. 170 The following rkt command: 171 172 ``` 173 $ rkt run example.com/hello:0.0.1 174 ``` 175 176 results in rkt retrieving the following URIs: 177 178 ``` 179 https://example.com/hello?ac-discovery=1 180 https://example.com/images/example.com/hello-0.0.1-linux-amd64.aci 181 https://example.com/images/example.com/hello-0.0.1-linux-amd64.aci.asc 182 ``` 183 184 The first response contains the template URL used to download the ACI and detached signature file. 185 186 ``` 187 <meta name="ac-discovery" content="example.com/hello https://example.com/images/{name}-{version}-{os}-{arch}.{ext}"> 188 ``` 189 190 rkt populates the `{os}` and `{arch}` based on the current running system. 191 The `{version}` will be taken from the tag given on the command line or "latest" if not supplied. 192 The `{ext}` will be substituted appropriately depending on artifact being retrieved: .aci will be used for ACI images and .aci.asc will be used for detached signatures. 193 194 Once the ACI image has been downloaded rkt will extract the image's name from the image metadata. 195 The image's name will be used to locate trusted public keys in the rkt keystore and perform signature validation. 196 197 ## Verifying Images with rkt 198 199 ### Establishing Trust 200 201 By default rkt does not trust any signing keys. 202 Trust is established by storing public keys in the rkt keystore. 203 This can be done using [`rkt trust`][rkt-trust] or manually, using the procedures described in the next section. 204 205 The following directories make up the default rkt keystore layout: 206 207 ``` 208 /etc/rkt/trustedkeys/root.d 209 /etc/rkt/trustedkeys/prefix.d 210 /usr/lib/rkt/trustedkeys/root.d 211 /usr/lib/rkt/trustedkeys/prefix.d 212 ``` 213 214 System administrators should store trusted keys under `/etc/rkt` as `/usr/lib/rkt` is designed to be used by the OS distribution. 215 Trusted keys are saved in the desired directory named after the fingerprint of the public key. 216 System administrators can "disable" a trusted key by writing an empty file under `/etc/rkt`. 217 For example, if your OS distribution shipped with the following trusted key: 218 219 ``` 220 /usr/lib/rkt/trustedkeys/prefix.d/coreos.com/a175e31de7e3c5b9d2c4603e4dfb22bf75ef7a23 221 ``` 222 223 you can disable it by writing the following empty file: 224 225 ``` 226 /etc/rkt/trustedkeys/prefix.d/coreos.com/a175e31de7e3c5b9d2c4603e4dfb22bf75ef7a23 227 ``` 228 229 ### Trusting the example.com/hello key 230 231 As an example, let's look at how we can trust a key used to sign images of the prefix `example.com/hello` 232 233 #### Using rkt trust 234 235 The easiest way to trust a key is to use the [`rkt trust`][rkt-trust] subcommand. 236 In this case, we directly pass it the URI containing the public key we wish to trust: 237 238 ``` 239 $ rkt trust --prefix=example.com/hello https://example.com/pubkeys.gpg 240 Prefix: "example.com/hello" 241 Key: "https://example.com/aci-pubkeys.gpg" 242 GPG key fingerprint is: B346 E31D E7E3 C6F9 D1D4 603F 4DFB 61BF 26EF 7A14 243 Carly Container (ACI signing key) <carly@example.com> 244 Are you sure you want to trust this key (yes/no)? yes 245 Trusting "https://example.com/aci-pubkeys.gpg" for prefix "example.com/hello". 246 Added key for prefix "example.com/hello" at "/etc/rkt/trustedkeys/prefix.d/example.com/hello/b346e31de7e3c6f9d1d4603f4dfb61bf26ef7a14" 247 ``` 248 249 Now the public key with fingerprint `b346e31de7e3c6f9d1d4603f4dfb61bf26ef7a14` will be trusted for all images with a name prefix of `example.com/hello`. 250 251 #### Manually adding keys 252 253 An alternative to using [`rkt trust`][rkt-trust] is to manually trust keys by adding them to rkt's database. 254 We do this by downloading the key, capturing its fingerprint, and storing it in the database using the fingerprint as filename 255 256 ##### Download the public key 257 258 ``` 259 $ curl -O https://example.com/pubkeys.gpg 260 ``` 261 262 ###### Capture the public key fingerprint 263 264 ``` 265 $ gpg --no-default-keyring --with-fingerprint --keyring ./pubkeys.gpg carly@example.com 266 pub 2048R/26EF7A14 2015-01-09 267 Key fingerprint = B346 E31D E7E3 C6F9 D1D4 603F 4DFB 61BF 26EF 7A14 268 uid [ unknown] Carly Container (ACI signing key) <carly@example.com> 269 sub 2048R/B9C074CD 2015-01-09 270 ``` 271 272 Remove white spaces and convert to lowercase: 273 274 ``` 275 $ echo "B346 E31D E7E3 C6F9 D1D4 603F 4DFB 61BF 26EF 7A14" | \ 276 tr -d "[:space:]" | tr '[:upper:]' '[:lower:]' 277 ``` 278 279 ``` 280 b346e31de7e3c6f9d1d4603f4dfb61bf26ef7a14 281 ``` 282 283 ##### Trust the key for the example.com/hello prefix 284 285 ``` 286 mkdir -p /etc/rkt/trustedkeys/prefix.d/example.com/hello 287 mv pubkeys.gpg /etc/rkt/trustedkeys/prefix.d/example.com/hello/b346e31de7e3c6f9d1d4603f4dfb61bf26ef7a14 288 ``` 289 290 Now the public key with fingerprint `b346e31de7e3c6f9d1d4603f4dfb61bf26ef7a14` will be trusted for all images with a name prefix of `example.com/hello`. 291 292 #### Trusting a key globally 293 294 If you would like to trust a public key for _any_ image, store the public key in one of the following "root" directories: 295 296 ``` 297 /etc/rkt/trustedkeys/root.d 298 /usr/lib/rkt/trustedkeys/root.d 299 ``` 300 301 ### Example Usage 302 303 #### Download, verify and run an ACI 304 305 By default rkt will attempt to download the ACI detached signature and verify the image: 306 307 ``` 308 # rkt run example.com/hello:0.0.1 309 rkt: starting to discover app img example.com/hello:0.0.1 310 rkt: starting to fetch img from http://example.com/images/example.com/hello-0.0.1-linux-amd64.aci 311 Downloading aci: [ ] 7.24 KB/1.26 MB 312 rkt: example.com/hello:0.0.1 verified signed by: 313 Carly Container (ACI signing key) <carly@example.com> 314 /etc/localtime is not a symlink, not updating container timezone. 315 ^]^]Container stage1 terminated by signal KILL. 316 ``` 317 318 Use the `--insecure-options=image` flag to disable image verification for a single run: 319 320 ``` 321 # rkt --insecure-options=image run example.com/hello:0.0.1 322 rkt: starting to discover app img example.com/hello:0.0.1 323 rkt: starting to fetch img from http://example.com/images/example.com/hello-0.0.1-linux-amd64.aci 324 rkt: warning: image signature verification has been disabled 325 Downloading aci: [= ] 32.8 KB/1.26 MB 326 /etc/localtime is not a symlink, not updating container timezone. 327 ^]^]Container stage1 terminated by signal KILL. 328 ``` 329 330 Notice when the `--insecure-options=image` flag is used, rkt will print the following warning: 331 332 ``` 333 rkt: warning: image signature verification has been disabled 334 ``` 335 336 #### Download and verify an ACI 337 338 Using the [`fetch`][rkt-fetch] subcommand you can download and verify an ACI without immediately running a pod. 339 This can be useful to precache ACIs on a large number of hosts: 340 341 ``` 342 # rkt fetch example.com/hello:0.0.1 343 rkt: starting to discover app img example.com/hello:0.0.1 344 rkt: starting to fetch img from http://example.com/images/example.com/hello-0.0.1-linux-amd64.aci 345 Downloading aci: [ ] 14.5 KB/1.26 MB 346 rkt: example.com/hello:0.0.1 verified signed by: 347 Carly Container (ACI signing key) <carly@example.com> 348 sha512-b3f138e10482d4b5f334294d69ae5c40 349 ``` 350 351 As before, use the `--insecure-options=image` flag to disable image verification: 352 353 ``` 354 # rkt --insecure-options=image fetch example.com/hello:0.0.1 355 rkt: starting to discover app img example.com/hello:0.0.1 356 rkt: starting to fetch img from http://example.com/images/example.com/hello-0.0.1-linux-amd64.aci 357 rkt: warning: image signature verification has been disabled 358 Downloading aci: [ ] 4.34 KB/1.26 MB 359 sha512-b3f138e10482d4b5f334294d69ae5c40 360 ``` 361 362 363 [getting-started]: getting-started-guide.md 364 [rkt-fetch]: subcommands/fetch.md 365 [rkt-trust]: subcommands/trust.md