summaryrefslogtreecommitdiff
path: root/scripts/image_signing/sign_oci_container.sh
blob: df3eb0fae93d3e8a9b3d25a5f3714ed0b8929950 (plain)
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
#!/bin/bash
# Copyright 2017 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

. "$(dirname "$0")/common.sh"

load_shflags || exit 1

DEFINE_string output "" \
  "Where to write signed output to (default: sign in-place)"

FLAGS_HELP="Usage: ${PROG} [options] <input_container> <key_dir>

Signs <input_container> with keys in <key_dir>.  Should have a config.json
file in the OCI format.

Input can be an unpacked container, or a CRX/ZIP file.
"

# Parse command line.
FLAGS "$@" || exit 1
eval set -- "${FLAGS_ARGV}"

# Abort on error.
set -e

# Sign the directory holding OCI container(s).  We look for manifest.json files.
sign_oci_container() {
  [[ $# -eq 3 ]] || die "Usage: sign_oci_container <input> <key> <output>"
  local input="${1%/}"
  local key_file="$2"
  local output="$3"

  if [[ "${input}" != "${output}" ]]; then
    rsync -a "${input}/" "${output}/"
  fi

  local manifest out_manifest
  while read -d $'\0' -r manifest; do
    out_manifest="${output}/${manifest}.sig"
    manifest="${input}/${manifest}"
    info "Signing: ${manifest}"
    if ! openssl dgst -sha256 -sign "${key_file}" \
                      -out "${out_manifest}" "${manifest}"; then
      die "Failed to sign"
    fi
  done < <(find "${input}/" -name manifest.json -printf '%P\0')
}

# Sign the crx/zip holding OCI container(s).  We look for manifest.json files.
sign_oci_container_zip() {
  [[ $# -eq 3 ]] || die "Usage: sign_oci_container_zip <input> <key> <output>"
  local input="$1"
  local key_file="$2"
  local output="$3"
  local tempdir=$(make_temp_dir)

  info "Unpacking archive: ${input}"
  unzip -q "${input}" -d "${tempdir}"

  sign_oci_container "${tempdir}" "${key_file}" "${tempdir}"

  rm -f "${output}"
  info "Packing archive: ${output}"
  (
    cd "${tempdir}"
    zip -q -r - ./
  ) >"${output}"
}

main() {
  if [[ $# -ne 2 ]]; then
    flags_help
    exit 1
  fi

  local input="${1%/}"
  local key_dir="$2"

  local key_file="${key_dir}/cros-oci-container.pem"
  if [[ ! -e "${key_file}" ]]; then
    die "Missing key file: ${key_file}"
  fi

  : "${FLAGS_output:=${input}}"

  if [[ -f "${input}" ]]; then
    sign_oci_container_zip "${input}" "${key_file}" "${FLAGS_output}"
  else
    sign_oci_container "${input}" "${key_file}" "${FLAGS_output}"
  fi
}
main "$@"