diff --git a/.bazelrc b/.bazelrc index 0413b35d7..87d834bfe 100644 --- a/.bazelrc +++ b/.bazelrc @@ -8,4 +8,4 @@ test:release --workspace_status_command=./private/stamp.bash --stamp # Allow external dependencies to be retried. debian snapshot is unreliable and needs retries. common --experimental_repository_downloader_retries=20 -common --http_timeout_scaling=2.0 \ No newline at end of file +common --http_timeout_scaling=2.0 diff --git a/WORKSPACE b/WORKSPACE index 48b95e3d6..2a750b9af 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -5,9 +5,9 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") # rules_distroless setup http_archive( name = "rules_distroless", - sha256 = "4b6d6a4bd03431f4f680ff5f6feea0b8ccf52c0296a12818d2c9595392e45543", - strip_prefix = "rules_distroless-0.2.0", - url = "https://github.com/GoogleContainerTools/rules_distroless/releases/download/v0.2.0/rules_distroless-v0.2.0.tar.gz", + sha256 = "9306b5b8a296d95745d7b38be20c320db125f1b5f6fc3ad507de21c8d562b159", + strip_prefix = "rules_distroless-896a27f8aee503c6ea3eeae47b51a4fc84c8496a", + url = "https://github.com/GoogleContainerTools/rules_distroless/archive/896a27f8aee503c6ea3eeae47b51a4fc84c8496a.tar.gz", ) load("@rules_distroless//distroless:dependencies.bzl", "distroless_dependencies") @@ -162,11 +162,3 @@ load("@rules_rust//rust:repositories.bzl", "rust_register_toolchains", "rust_rep rust_repositories(edition = "2021") rust_register_toolchains() - -# rules_docker setup. -# NOTE: this ruleset is almost unused and replaced by rules_oci completely expect a few helper macros that'll be hosted on distroless-tools. -http_archive( - name = "io_bazel_rules_docker", - sha256 = "b1e80761a8a8243d03ebca8845e9cc1ba6c82ce7c5179ce2b295cd36f7e394bf", - urls = ["https://github.com/bazelbuild/rules_docker/releases/download/v0.25.0/rules_docker-v0.25.0.tar.gz"], -) diff --git a/base/BUILD b/base/BUILD index 0eaed1768..76c0aaafd 100644 --- a/base/BUILD +++ b/base/BUILD @@ -1,102 +1,9 @@ -load(":base.bzl", "NONROOT", "distro_components") +load(":base.bzl", "base_images") load(":distro.bzl", "DISTROS") -load("@rules_pkg//:pkg.bzl", "pkg_tar") -load("@io_bazel_rules_docker//contrib:group.bzl", "group_entry", "group_file") -load("@io_bazel_rules_docker//contrib:passwd.bzl", "passwd_entry", "passwd_tar") package(default_visibility = ["//visibility:public"]) -NOBODY = 65534 - -# Create /etc/passwd with the root user -passwd_entry( - name = "root_user", - gid = 0, - home = "/root", - info = "root", - shell = "/sbin/nologin", - uid = 0, - username = "root", -) - -passwd_entry( - name = "nobody_user", - create_home = False, - gid = NOBODY, - home = "/nonexistent", - info = "nobody", - shell = "/sbin/nologin", - uid = NOBODY, - username = "nobody", -) - -passwd_entry( - name = "nonroot_user", - gid = NONROOT, - home = "/home/nonroot", - info = "nonroot", - shell = "/sbin/nologin", - uid = NONROOT, - username = "nonroot", -) - -passwd_tar( - name = "passwd", - entries = [ - ":root_user", - ":nobody_user", - ":nonroot_user", - ], - passwd_file_pkg_dir = "etc", -) - -# Create /etc/group with the root, tty, and staff groups -group_entry( - name = "root_group", - gid = 0, - groupname = "root", -) - -group_entry( - name = "nobody_group", - gid = NOBODY, - groupname = "nobody", -) - -group_entry( - name = "nonroot_group", - gid = NONROOT, - groupname = "nonroot", -) - -group_entry( - name = "tty_group", - gid = 5, - groupname = "tty", -) - -group_entry( - name = "staff_group", - gid = 50, - groupname = "staff", -) - -group_file( - name = "group", - entries = [ - ":root_group", - ":nobody_group", - ":tty_group", - ":staff_group", - ":nonroot_group", - ], -) - -pkg_tar( - name = "group_tar", - srcs = [":group"], - mode = "0644", - package_dir = "etc", -) - -[distro_components(distro) for distro in DISTROS] +[ + base_images(distro = distro) + for distro in DISTROS +] diff --git a/base/base.bzl b/base/base.bzl index 00a89e953..1d656a4b7 100644 --- a/base/base.bzl +++ b/base/base.bzl @@ -5,19 +5,17 @@ load("@io_bazel_rules_go//go:def.bzl", "go_binary") load("@rules_oci//oci:defs.bzl", "oci_image", "oci_image_index") load("@rules_pkg//:pkg.bzl", "pkg_tar") load("//:checksums.bzl", "ARCHITECTURES", "VARIANTS") -load("//cacerts:cacerts.bzl", "cacerts") +load("//common:variables.bzl", "NONROOT") +load("//private/util:deb.bzl", "deb") -NONROOT = 65532 +USER_VARIANTS = [("root", 0, "/"), ("nonroot", NONROOT, "/home/nonroot")] -def deb_file(arch, distro, package): - return "@{arch}_{distro}_{package}//:data".format(arch = arch, distro = distro, package = package) +def base_images(distro): + """Replicate everything for all distroless suffixes -def deb_pkg(arch, distro, package): - return "@{arch}_{distro}_{package}".format(arch = arch, distro = distro, package = package) - -# Replicate everything for all distroless suffixes -def distro_components(distro): - USER_VARIANTS = [("root", 0, "/"), ("nonroot", NONROOT, "/home/nonroot")] + Args: + distro: name of the distribution + """ # loop for multi-arch images for (user, _, _) in USER_VARIANTS: @@ -70,11 +68,6 @@ def distro_components(distro): ) for arch in ARCHITECTURES: - cacerts( - name = "cacerts_" + arch + "_" + distro, - deb = deb_file(arch, distro, "ca-certificates"), - ) - for (user, uid, workdir) in USER_VARIANTS: oci_image( name = "static_" + user + "_" + arch + "_" + distro, @@ -86,20 +79,19 @@ def distro_components(distro): "SSL_CERT_FILE": "/etc/ssl/certs/ca-certificates.crt", }, tars = [ - deb_pkg(arch, distro, "base-files"), - deb_pkg(arch, distro, "netbase"), - deb_pkg(arch, distro, "tzdata"), - ":passwd", - ":group_tar", - + deb.package(arch, distro, "base-files"), + deb.package(arch, distro, "netbase"), + deb.package(arch, distro, "tzdata"), + "//common:rootfs", + "//common:passwd", + "//common:home", + "//common:group", # Create /tmp, too many things assume it exists. # tmp.tar has a /tmp with the correct permissions 01777 - # A tar is needed because at the moment there is no way to create a - # directory with specific permissions. - ":tmp.tar", + "//common:tmp", ":nsswitch.tar", - "//os_release:os_release_" + distro + ".tar", - ":cacerts_" + arch + "_" + distro + ".tar", + "//common:os_release_" + distro, + "//common:cacerts_" + distro + "_" + arch, ], user = "%d" % uid, workdir = workdir, @@ -112,7 +104,7 @@ def distro_components(distro): name = "base_nossl_" + user + "_" + arch + "_" + distro, base = ":static_" + user + "_" + arch + "_" + distro, tars = [ - deb_pkg(arch, distro, "libc6"), + deb.package(arch, distro, "libc6"), ], ) @@ -131,10 +123,10 @@ def distro_components(distro): name = "base_" + user + "_" + arch + "_" + distro, base = ":static_" + user + "_" + arch + "_" + distro, tars = [ - deb_pkg(arch, distro, "libc6"), + deb.package(arch, distro, "libc6"), ] + [ - deb_pkg(arch, distro, deb) - for deb in BASE_DISTRO_DEBS[distro] + deb.package(arch, distro, pkg) + for pkg in BASE_DISTRO_DEBS[distro] ], ) diff --git a/base/tmp.tar b/base/tmp.tar deleted file mode 100644 index ee83747f6..000000000 Binary files a/base/tmp.tar and /dev/null differ diff --git a/cacerts/BUILD b/cacerts/BUILD deleted file mode 100644 index 58e0e9a74..000000000 --- a/cacerts/BUILD +++ /dev/null @@ -1 +0,0 @@ -package(default_visibility = ["//:__subpackages__"]) diff --git a/cacerts/cacerts.bzl b/cacerts/cacerts.bzl deleted file mode 100644 index 5265636f1..000000000 --- a/cacerts/cacerts.bzl +++ /dev/null @@ -1,58 +0,0 @@ -"""A rule to unpack ca certificates from the debian package.""" - -load("@rules_pkg//:providers.bzl", "PackageFilesInfo") -load("@rules_pkg//:pkg.bzl", "pkg_tar") - -CMD = """\ -#!/usr/bin/env bash -set -o pipefail -o errexit -o nounset - -tmp=$(mktemp -d) -tar -xf "$1" -C "$tmp" ./usr/share/ca-certificates ./usr/share/doc/ca-certificates/copyright - -cp "$tmp/usr/share/doc/ca-certificates/copyright" $3 - -CERTS=$(find $tmp/usr/share/ca-certificates -type f | sort) -for cert in $CERTS; do - cat $cert >> $2 -done -""" - -def _impl(ctx): - ca_certificates = ctx.actions.declare_file("ca_certificates_{}.crt".format(ctx.label.name)) - copyright = ctx.actions.declare_file("ca_certificates_copyright_{}".format(ctx.label.name)) - ctx.actions.run_shell( - inputs = [ctx.file.deb], - outputs = [ca_certificates, copyright], - arguments = [ - ctx.file.deb.path, - ca_certificates.path, - copyright.path, - ], - command = CMD, - ) - - files = { - "/etc/ssl/certs/ca-certificates.crt": ca_certificates, - "/usr/share/doc/ca-certificates/copyright": copyright, - } - - return [ - DefaultInfo(files = depset([ca_certificates, copyright])), - PackageFilesInfo(dest_src_map = files), - ] - -_cacerts = rule( - attrs = { - "deb": attr.label( - allow_single_file = [".tar.xz"], - mandatory = True, - ), - }, - executable = False, - implementation = _impl, -) - -def cacerts(name, deb, **kwargs): - _cacerts(name = "%s_extract" % name, deb = deb, **kwargs) - pkg_tar(name = name, srcs = ["%s_extract" % name], **kwargs) diff --git a/cacerts/java.bzl b/cacerts/java.bzl deleted file mode 100644 index fad56622a..000000000 --- a/cacerts/java.bzl +++ /dev/null @@ -1,61 +0,0 @@ -# Copyright 2017 Google Inc. All rights reserved. - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -"extract ca-certificates and converts to version 2 JKS from PEM-encoded x509 certs" - -load("@rules_pkg//:providers.bzl", "PackageFilesInfo") -load("@rules_pkg//:pkg.bzl", "pkg_tar") - -CMD = """\ -#!/usr/bin/env bash -set -o pipefail -o errexit -tar -xOf "$1" etc/ssl/certs/ca-certificates.crt | $3 > $2 -""" - -def _impl(ctx): - cacerts = ctx.actions.declare_file(ctx.label.name) - ctx.actions.run_shell( - outputs = [cacerts], - inputs = [ctx.file.cacerts_tar], - tools = [ctx.file._jksutil], - arguments = [ctx.file.cacerts_tar.path, cacerts.path, ctx.executable._jksutil.path], - command = CMD, - ) - return [ - DefaultInfo(files = depset([cacerts])), - PackageFilesInfo(dest_src_map = {"/etc/ssl/certs/java/cacerts": cacerts}), - ] - -_cacerts_java = rule( - doc = """ -Rule for converting the PEM formatted ca-certs in to JKS format. Output is a tar -file with the JKS file at etc/ssl/certs/java/cacerts. -""", - attrs = { - "cacerts_tar": attr.label( - allow_single_file = [".tar"], - mandatory = True, - ), - "_jksutil": attr.label( - default = Label("//cacerts/jksutil:jksutil"), - cfg = "host", - executable = True, - allow_single_file = True, - ), - }, - implementation = _impl, -) - -def cacerts_java(name, cacerts_tar, **kwargs): - _cacerts_java(name = "%s_extract" % name, cacerts_tar = cacerts_tar, **kwargs) - pkg_tar(name = name, srcs = ["%s_extract" % name], **kwargs) diff --git a/cacerts/jksutil/BUILD b/cacerts/jksutil/BUILD deleted file mode 100644 index 638826837..000000000 --- a/cacerts/jksutil/BUILD +++ /dev/null @@ -1,50 +0,0 @@ -load( - "@io_bazel_rules_go//go:def.bzl", - "go_binary", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = [ - "certificate.go", - "jks.go", - ], - importpath = "github.com/distroless/cacerts/jksutil", -) - -go_test( - name = "test", - size = "small", - srcs = [ - "certificate_test.go", - ], - embed = [":go_default_library"], -) - -go_binary( - name = "jksutil", - srcs = [ - "certificate.go", - "jks.go", - "main.go", - ], - visibility = [ - "//visibility:public", - ], - deps = [ - ":go_default_library", - ], -) - -sh_test( - name = "test_sh", - size = "small", - srcs = ["test_jks.sh"], - args = ["$(location :jksutil)"], - data = [ - "test.crt", - ":jksutil", - ], -) diff --git a/cacerts/jksutil/README.md b/cacerts/jksutil/README.md deleted file mode 100644 index 0bf461efe..000000000 --- a/cacerts/jksutil/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Java Key Store - -A utility for converting public PEM certs to a Java Key Store. - - cat /etc/ssl/certs/*.pem | ./jksutil > /etc/ssl/certs/java/cacerts diff --git a/cacerts/jksutil/certificate.go b/cacerts/jksutil/certificate.go deleted file mode 100644 index bc6b007de..000000000 --- a/cacerts/jksutil/certificate.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2020 Google Inc. All rights reserved. - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 - -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License.ackage jksutil - -package main - -import ( - "crypto/x509" - "encoding/pem" - "fmt" -) - -// Parses a series of PEM-encoded x509 certificates -func ParsePEMCertificates(pemCerts []byte) ([]*x509.Certificate, error) { - var certs []*x509.Certificate - for len(pemCerts) > 0 { - var block *pem.Block - block, pemCerts = pem.Decode(pemCerts) - if block == nil { - break - } - if block.Type != "CERTIFICATE" || len(block.Headers) != 0 { - return nil, fmt.Errorf("Non-certificate PEM: %v", block) - } - cert, err := x509.ParseCertificate(block.Bytes) - if err != nil { - return nil, err - } - certs = append(certs, cert) - } - return certs, nil -} diff --git a/cacerts/jksutil/certificate_test.go b/cacerts/jksutil/certificate_test.go deleted file mode 100644 index c895e4a9d..000000000 --- a/cacerts/jksutil/certificate_test.go +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright 2020 Google Inc. All rights reserved. - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 - -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License.ackage jksutil - -package main - -import ( - "strings" - "testing" -) - -const validPEMCerts = ` ------BEGIN CERTIFICATE----- -MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE -AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw -CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ -BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND -VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb -qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY -HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo -G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA -lHPrzg5XPAOBOp0KoVdDaaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhr -IA8wKFSVf+DuzgpmndFALW4ir50awQUZ0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/ -0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH -k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47 -4KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMO -m3WR5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpa -cXpkatcnYGMN285J9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPl -uUsXQA+xtrn13k/c4LOsOxFwYIRKQ26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYI -KwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRwOi8vd3d3LmFjY3YuZXMvZmls -ZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEuY3J0MB8GCCsG -AQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 -VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeT -VfZW6oHlNsyMHj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIG -CCsGAQUFBwICMIIBFB6CARAAQQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUA -cgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBhAO0AegAgAGQAZQAgAGwAYQAgAEEA -QwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUAYwBuAG8AbABvAGcA -7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBjAHQA -cgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAA -QwBQAFMAIABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUA -czAwBggrBgEFBQcCARYkaHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2Mu -aHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRt -aW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2MV9kZXIuY3JsMA4GA1Ud -DwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZIhvcNAQEF -BQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdp -D70ER9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gU -JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m -AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD -vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms -tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH -7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h -I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA -h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF -d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H -pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UE -AwwNQUNFRElDT00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00x -CzAJBgNVBAYTAkVTMB4XDTA4MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEW -MBQGA1UEAwwNQUNFRElDT00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZF -RElDT00xCzAJBgNVBAYTAkVTMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC -AgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7w2rbYgIB8hiGtXxaOLHkWLn7 -09gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auODAKgrLlUTY4HKRxx7 -XBZXehuDYAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW10W2ZEi5P -Grjm6gSSrj0RuVFCPYewMYWveVqc/udOXpJPQ/yrOq2lEiZmueIM15jO1FillUAK -t0SdE3QrwqXrIhWYENiLxQSfHY9g5QYbm8+5eaA9oiM/Qj9r+hwDezCNzmzAv+Yb -X79nuIQZ1RXve8uQNjFiybwCq0Zfm/4aaJQ0PZCOrfbkHQl/Sog4P75n/TSW9R28 -MHTLOO7VbKvU/PQAtwBbhTIWdjPp2KOZnQUAqhbm84F9b32qhm2tFXTTxKJxqvQU -fecyuB+81fFOvW8XAjnXDpVCOscAPukmYxHqC9FK/xidstd7LzrZlvvoHpKuE1XI -2Sf23EgbsCTBheN3nZqk8wwRHQ3ItBTutYJXCb8gWH8vIiPYcMt5bMlL8qkqyPyH -K9caUPgn6C9D4zq92Fdx/c6mUlv53U3t5fZvie27k5x2IXXwkkwp9y+cAS7+UEae -ZAwUswdbxcJzbPEHXEUkFDWug/FqTYl6+rPYLWbwNof1K1MCAwEAAaOBqjCBpzAP -BgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKaz4SsrSbbXc6GqlPUB53NlTKxQ -MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUprPhKytJttdzoaqU9QHnc2VMrFAw -RAYDVR0gBD0wOzA5BgRVHSAAMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly9hY2VkaWNv -bS5lZGljb21ncm91cC5jb20vZG9jMA0GCSqGSIb3DQEBBQUAA4ICAQDOLAtSUWIm -fQwng4/F9tqgaHtPkl7qpHMyEVNEskTLnewPeUKzEKbHDZ3Ltvo/Onzqv4hTGzz3 -gvoFNTPhNahXwOf9jU8/kzJPeGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKe -I6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH1PwkzQSulgUV1qzOMPPKC8W64iLgpq0i -5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf8seACQl1ThCojz2GuHURwCRi -ipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7tq3PgbUhh8oIKiMn -MCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtPF2Y9fwsZ -o5NjEFIqnxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6 -zqylfDJKZ0DcMDQj3dcEI2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacN -GHk0vFQYXlPKNFHtRQrmjseCNj6nOGOpMCwXEGCSn1WHElkQwg9naRHMTh5+Spqt -r0CodaxWkHS4oJyleW/c6RrIaQXpuvoDs3zk4E7Czp3otkYNbn5XOmeUwssfnHdK -Z05phkOTOPu220+DkdRgfks+KzgHVZhepA== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIGZjCCBE6gAwIBAgIPB35Sk3vgFeNX8GmMy+wMMA0GCSqGSIb3DQEBBQUAMHsx -CzAJBgNVBAYTAkNPMUcwRQYDVQQKDD5Tb2NpZWRhZCBDYW1lcmFsIGRlIENlcnRp -ZmljYWNpw7NuIERpZ2l0YWwgLSBDZXJ0aWPDoW1hcmEgUy5BLjEjMCEGA1UEAwwa -QUMgUmHDrXogQ2VydGljw6FtYXJhIFMuQS4wHhcNMDYxMTI3MjA0NjI5WhcNMzAw -NDAyMjE0MjAyWjB7MQswCQYDVQQGEwJDTzFHMEUGA1UECgw+U29jaWVkYWQgQ2Ft -ZXJhbCBkZSBDZXJ0aWZpY2FjacOzbiBEaWdpdGFsIC0gQ2VydGljw6FtYXJhIFMu -QS4xIzAhBgNVBAMMGkFDIFJhw616IENlcnRpY8OhbWFyYSBTLkEuMIICIjANBgkq -hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAq2uJo1PMSCMI+8PPUZYILrgIem08kBeG -qentLhM0R7LQcNzJPNCNyu5LF6vQhbCnIwTLqKL85XXbQMpiiY9QngE9JlsYhBzL -fDe3fezTf3MZsGqy2IiKLUV0qPezuMDU2s0iiXRNWhU5cxh0T7XrmafBHoi0wpOQ -Y5fzp6cSsgkiBzPZkc0OnB8OIMfuuzONj8LSWKdf/WU34ojC2I+GdV75LaeHM/J4 -Ny+LvB2GNzmxlPLYvEqcgxhaBvzz1NS6jBUJJfD5to0EfhcSM2tXSExP2yYe68yQ -54v5aHxwD6Mq0Do43zeX4lvegGHTgNiRg0JaTASJaBE8rF9ogEHMYELODVoqDA+b -MMCm8Ibbq0nXl21Ii/kDwFJnmxL3wvIumGVC2daa49AZMQyth9VXAnow6IYm+48j -ilSH5L887uvDdUhfHjlvgWJsxS3EF1QZtzeNnDeRyPYL1epjb4OsOMLzP96a++Ej -YfDIJss2yKHzMI+ko6Kh3VOz3vCaMh+DkXkwwakfU5tTohVTP92dsxA7SH2JD/zt -A/X7JWR1DhcZDY8AFmd5ekD8LVkH2ZD6mq093ICK5lw1omdMEWux+IBkAC1vImHF -rEsm5VoQgpukg3s0956JkSCXjrdCx2bD0Omk1vUgjcTDlaxECp1bczwmPS9KvqfJ -pxAe+59QafMCAwEAAaOB5jCB4zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE -AwIBBjAdBgNVHQ4EFgQU0QnQ6dfOeXRU+Tows/RtLAMDG2gwgaAGA1UdIASBmDCB -lTCBkgYEVR0gADCBiTArBggrBgEFBQcCARYfaHR0cDovL3d3dy5jZXJ0aWNhbWFy -YS5jb20vZHBjLzBaBggrBgEFBQcCAjBOGkxMaW1pdGFjaW9uZXMgZGUgZ2FyYW50 -7WFzIGRlIGVzdGUgY2VydGlmaWNhZG8gc2UgcHVlZGVuIGVuY29udHJhciBlbiBs -YSBEUEMuMA0GCSqGSIb3DQEBBQUAA4ICAQBclLW4RZFNjmEfAygPU3zmpFmps4p6 -xbD/CHwso3EcIRNnoZUSQDWDg4902zNc8El2CoFS3UnUmjIz75uny3XlesuXEpBc -unvFm9+7OSPI/5jOCk0iAUgHforA1SBClETvv3eiiWdIG0ADBaGJ7M9i4z0ldma/ -Jre7Ir5v/zlXdLp6yQGVwZVR6Kss+LGGIOk/yzVb0hfpKv6DExdA7ohiZVvVO2Dp -ezy4ydV/NgIlqmjCMRW3MGXrfx1IebHPOeJCgBbT9ZMj/EyXyVo3bHwi2ErN0o42 -gzmRkBDI8ck1fj+404HGIGQatlDCIaR43NAvO2STdPCWkPHv+wlaNECW8DYSwaN0 -jJN+Qd53i+yG2dIPPy3RzECiiWZIHiCznCNZc6lEc7wkeZBWN7PGKX6jD/EpOe9+ -XCgycDWs2rjIdWb8m0w5R44bb5tNAlQiM+9hup4phO9OSzNHdpdqy35f/RWmnkJD -W2ZaiogN9xa5P1FlK2Zqi9E4UqLWRhH6/JocdJ6PlwsCT2TG9WjTSy3/pDceiz+/ -RL5hRqGEPQgnTIEgd4kI6mdAXmwIUV80WoyWaM3X94nCHNMyAK9Sy9NgWyo6R35r -MDOhYil/SrnhLecUIw4OGEfhefwVVdCx/CVxY3UzHCMrr1zZ7Ud3YA47Dx7SwNxk -BYn8eNZcLCZDqQ== ------END CERTIFICATE----- -` - -const nonCert = ` ------BEGIN CERTIFICATE REQUEST----- -MIICXTCCAUUCAQAwGDEWMBQGA1UEAwwNaGkgd2lraXBlZGlhITCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAMTwzCYD+iLlDwTu5Y43aQH9q1LF3kgot8I4 -9ZgbFhDmCE4YlLhZKO4hieK6z8z+IfZjfapn01rzuzvTHESj5bSSU6AcEsKSOgTQ -uB+KKn4mgngyBrJwWjr4IZ9XkGsCLAP2/wkyJC2ire6FuTSQ00YGhKf1B3WbIBbn -5i1rvZXnYxlheWlNSmxx54q4gTwcd/V4nS4BThYA/ypATjHS/gfQ650cOQzRK/Jh -WfAbfnETYUpD6MCgZAIbaBuYvYpQEGqQ4niTvtSd07RHKnewcPFqJhMV86qN4HQY -4ZBNzQcF/2aCGHYyRniKznSDNijT2kaAz/L7ORqh+90qH/BLnKsCAwEAAaAAMA0G -CSqGSIb3DQEBCwUAA4IBAQAqV5g9AZGXEbM97ouTGDJqFNP2QjO9ZK9J3BOUTrFO -tMUrVWj+ixhC6vXD3o5uVL/fg6OlmK+13gsBpzg2mq72TBrZsNOK4+O0XvltIvSx -0H5tf1NYwuHxFgHDqgs/fQBOKFTadebJZHbPBtMrqlnenKYJiVb5YSWBZ7JKRCK7 -VSgwNxxAMnSCNI0xF3EjZ1bjQkM8xGhnwe+n/RAd5Q2pMLIrquMoGMTUYLOq1xSB -sGTp8iLWbbWPl6gC1hcSMpFsbdyjMCWs+a2R2F8QnahrRfvpgFEndvzA2EvqHIoR -BHE1ChD7l691PxZP1eKA1I4AzZno5sb6SWyd8+pqY0oG ------END CERTIFICATE REQUEST----- -` - -func TestParseValidPEMCertificates(t *testing.T) { - certs, err := ParsePEMCertificates([]byte(validPEMCerts)) - if err != nil { - t.Errorf("Failed parsing: %v", err) - } - if len(certs) != 3 { - t.Errorf("Expected 3 certs, got %d", len(certs)) - } - expectedCNs := []string{ - "ACCVRAIZ1", "ACEDICOM Root", "AC Raíz Certicámara S.A."} - for i, expected := range expectedCNs { - actual := certs[i].Subject.CommonName - if certs[i].Subject.CommonName != expected { - t.Errorf("Expected CN of %s, got %s", expected, actual) - } - } -} - -func TestErrorOnNonCertificateTypes(t *testing.T) { - _, err := ParsePEMCertificates([]byte(validPEMCerts + nonCert)) - if !strings.Contains(err.Error(), "Non-certificate PEM") { - t.Errorf("Unexpected error %v", err) - } -} diff --git a/cacerts/jksutil/jks.go b/cacerts/jksutil/jks.go deleted file mode 100644 index d14114cdf..000000000 --- a/cacerts/jksutil/jks.go +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright 2020 Google Inc. All rights reserved. - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 - -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License.ackage jksutil - -// package jksutil allows interactions with a version 2 java key store -package main - -import ( - "crypto/sha1" - "crypto/x509" - "encoding/binary" - "hash" - "io" - "strings" - "unicode" -) - -const ( - // constants from the openjdk source - defaultPassword = "changeit" - keySalt = "Mighty Aphrodite" - // we only support writing the latest version - versionTag int32 = 2 - // private key entries use a tag of 1. We only support storing public certs, - // known as "trustedCertEntry" in JKS (tag 2). - trustedCertTag int32 = 2 -) - -var ( - // magic bytes for the header. - magic = []byte{0xfe, 0xed, 0xfe, 0xed} -) - -// Java Key Store format, as described by: -// share/classes/sun/security/provider/JavaKeyStore.java -// -// Magic number (big-endian integer), -// Version of this file format (big-endian integer), -// -// Count (big-endian integer), -// followed by "count" instances of either: -// -// { -// tag=1 (big-endian integer), -// alias (UTF string) -// timestamp -// encrypted private-key info according to PKCS #8 -// (integer length followed by encoding) -// cert chain (integer count, then certs; for each cert, -// integer length followed by encoding) -// } -// -// or: -// -// { -// tag=2 (big-endian integer) -// alias (UTF string) -// timestamp -// cert (integer length followed by encoding) -// } -// -// ended by a keyed SHA1 hash (bytes only) of -// { password + whitener + preceding body } -// -// NOTE: We only support writing trusted certs (tag=2) for now. -type JavaKeyStore struct { - password string - digest hash.Hash - trustedCerts []*x509.Certificate -} - -func NewJavaKeyStore( - password string, trustedCerts []*x509.Certificate) (*JavaKeyStore, error) { - - // We need to initialize the digest before anything is written. JKS adds some - // "key whitening" to the digest by interlacing the password with 0 bytes and - // adding a salt at the end. - digest := sha1.New() - buf := make([]byte, len(password)*2) - for i := 0; i < len(password); i++ { - buf[i*2] = password[i] >> 8 - buf[i*2+1] = password[i] - } - if _, err := digest.Write(buf); err != nil { - return nil, err - } - if _, err := digest.Write([]byte(keySalt)); err != nil { - return nil, err - } - - return &JavaKeyStore{ - password: password, - digest: digest, - trustedCerts: trustedCerts, - }, nil -} - -// Opens a new keystore using the default JKS password -func WithDefaultPassword( - trustedCerts []*x509.Certificate) (*JavaKeyStore, error) { - - return NewJavaKeyStore(defaultPassword, trustedCerts) -} - -func (ks *JavaKeyStore) Write(w io.Writer) error { - // we copy all writes to the digest - out := io.MultiWriter(w, ks.digest) - if err := ks.writeHeader(out); err != nil { - return err - } - if err := ks.writeKeys(out); err != nil { - return err - } - // sha1 digest is written at the end of the file - _, err := w.Write(ks.digest.Sum(nil)) - return err -} - -func (ks *JavaKeyStore) writeHeader(w io.Writer) error { - if _, err := w.Write(magic); err != nil { - return err - } - if err := bigEndianWrite(w, versionTag); err != nil { - return err - } - return bigEndianWrite(w, int32(len(ks.trustedCerts))) -} - -func (ks *JavaKeyStore) writeKeys(w io.Writer) error { - for _, cert := range ks.trustedCerts { - if err := bigEndianWrite(w, trustedCertTag); err != nil { - return err - } - alias := javaAliasName(cert) - if err := writeString(w, alias); err != nil { - return err - } - // this is supposed to be the epoch time (in ms) of when the certificate - // was added to the store. Just always using the 0 epoch to keep things - // reproducible. - if err := bigEndianWrite(w, int64(0)); err != nil { - return err - } - // The type of cert - if err := writeString(w, "X.509"); err != nil { - return err - } - // 4 byte int length + ASN.1 DER encoded cert - if err := bigEndianWrite(w, int32(len(cert.Raw))); err != nil { - return err - } - // cert.Raw already has the correct encoding - if _, err := w.Write(cert.Raw); err != nil { - return err - } - } - return nil -} - -// key store aliases should be lowercase and contain no spaces -func javaAliasName(cert *x509.Certificate) string { - return strings.Map(func(r rune) rune { - if unicode.IsSpace(r) { - return -1 - } - return unicode.ToLower(r) - }, cert.Subject.String()) -} - -func bigEndianWrite(w io.Writer, data interface{}) error { - return binary.Write(w, binary.BigEndian, data) -} - -// Strings are written as a 2 byte big-endian length + UTF-8 -func writeString(w io.Writer, data string) error { - // this is not correct...for strings the JKS uses a modified UTF 8 encoding - // as described here: - // https://docs.oracle.com/javase/7/docs/api/java/io/DataInput.html#modified-utf-8 - // This means we'll create a corrupt JKS if we encounter a certificate name - // with a null byte or a character greater than U+FFFF. It seems unlikely - // enough that we don't worry about doing the correct encoding. - if err := bigEndianWrite(w, int16(len(data))); err != nil { - return err - } - _, err := w.Write([]byte(data)) - return err -} diff --git a/cacerts/jksutil/main.go b/cacerts/jksutil/main.go deleted file mode 100644 index 83a288cb3..000000000 --- a/cacerts/jksutil/main.go +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2020 Google Inc. All rights reserved. - -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at - -// http://www.apache.org/licenses/LICENSE-2.0 - -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License.ackage jksutil - -package main - -import ( - "io/ioutil" - "log" - "os" -) - -func init() { - log.SetPrefix("[jksutil] ") - log.SetFlags(log.Lshortfile) -} - -// Reads PEM-encoded x509 certs from STDIN and writes a version 2 JKS to STDOUT -func main() { - pemCerts, err := ioutil.ReadAll(os.Stdin) - if err != nil { - panic(err) - } - certs, err := ParsePEMCertificates(pemCerts) - if err != nil { - panic(err) - } - keyStore, err := WithDefaultPassword(certs) - if err != nil { - panic(err) - } - if err = keyStore.Write(os.Stdout); err != nil { - panic(err) - } -} diff --git a/cacerts/jksutil/test.crt b/cacerts/jksutil/test.crt deleted file mode 100644 index 9247e5495..000000000 --- a/cacerts/jksutil/test.crt +++ /dev/null @@ -1,113 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF -ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6 -b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL -MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv -b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj -ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM -9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw -IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6 -VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L -93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm -jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC -AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA -A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI -U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs -N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv -o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU -5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy -rqXRfboQnoZsG4q5WTP468SQvvG5 ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv -b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG -EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl -cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi -MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c -JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP -mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ -wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 -VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ -AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB -AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW -BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun -pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC -dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf -fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm -NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx -H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe -+o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB -vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL -ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp -U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W -ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe -Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX -MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0 -IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y -IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh -bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF -AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF -9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH -H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H -LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN -/BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT -rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud -EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw -WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs -exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud -DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4 -sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+ -seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz -4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+ -BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR -lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3 -7M2CYfE45k+XmCpajQ== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G -A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp -Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 -MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG -A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL -v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 -eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq -tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd -C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa -zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB -mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH -V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n -bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG -3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs -J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO -291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS -ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd -AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 -TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G -A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp -Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 -MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG -A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI -hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 -RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT -gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm -KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd -QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ -XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw -DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o -LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU -RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp -jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK -6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX -mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs -Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH -WD9f ------END CERTIFICATE----- diff --git a/cacerts/jksutil/test_jks.sh b/cacerts/jksutil/test_jks.sh deleted file mode 100755 index 54c523a9f..000000000 --- a/cacerts/jksutil/test_jks.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/bash -eux - -# Copyright 2020 Google Inc. All rights reserved. - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at - -# http://www.apache.org/licenses/LICENSE-2.0 - -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -assert::file_contains() { - if grep -qF "$2" "$1"; then - return 0 - fi - return 2 -} - -cat cacerts/jksutil/test.crt | ./$1 > $TEST_TMPDIR/keys.jks - -# Keytool is included with the JRE for querying keystores -keytool -list -v -keystore $TEST_TMPDIR/keys.jks -storepass changeit \ - > $TEST_TMPDIR/keytool_output - -cat $TEST_TMPDIR/keytool_output - -cat $TEST_TMPDIR/keytool_output -assert::file_contains $TEST_TMPDIR/keytool_output \ - "Your keystore contains 5 entries" - -assert::file_contains $TEST_TMPDIR/keytool_output \ - "cn=verisignuniversalrootcertificationauthority,ou=verisigntrustnetwork+ou=(c)2008verisign\,inc.-forauthorizeduseonly,o=verisign\,inc.,c=us" -assert::file_contains $TEST_TMPDIR/keytool_output \ - "SHA1: 36:79:CA:35:66:87:72:30:4D:30:A5:FB:87:3B:0F:A7:7B:B7:0D:54" - -assert::file_contains $TEST_TMPDIR/keytool_output \ - "cn=amazonrootca1,o=amazon,c=us" -assert::file_contains $TEST_TMPDIR/keytool_output \ - "SHA1: 8D:A7:F9:65:EC:5E:FC:37:91:0F:1C:6E:59:FD:C1:CC:6A:6E:DE:16" - -assert::file_contains $TEST_TMPDIR/keytool_output \ - "cn=digicertassuredidrootca,ou=www.digicert.com,o=digicertinc,c=us" -assert::file_contains $TEST_TMPDIR/keytool_output \ - "SHA1: 05:63:B8:63:0D:62:D7:5A:BB:C8:AB:1E:4B:DF:B5:A8:99:B2:4D:43" - -assert::file_contains $TEST_TMPDIR/keytool_output \ - "cn=globalsign,ou=globalsignrootca-r3,o=globalsign" -assert::file_contains $TEST_TMPDIR/keytool_output \ - "SHA1: D6:9B:56:11:48:F0:1C:77:C5:45:78:C1:09:26:DF:5B:85:69:76:AD" - -assert::file_contains $TEST_TMPDIR/keytool_output \ - "cn=globalsign,ou=globalsignrootca-r2,o=globalsign" -assert::file_contains $TEST_TMPDIR/keytool_output \ - "SHA1: 75:E0:AB:B6:13:85:12:27:1C:04:F8:5F:DD:DE:38:E4:B7:24:2E:FE" diff --git a/cc/BUILD b/cc/BUILD index 0fd6fa575..0335ab068 100644 --- a/cc/BUILD +++ b/cc/BUILD @@ -1,7 +1,7 @@ load("@rules_oci//oci:defs.bzl", "oci_image", "oci_image_index") -load("//base:distro.bzl", "DISTROS") -load("//base:base.bzl", "deb_pkg") load("//:checksums.bzl", "ARCHITECTURES") +load("//base:distro.bzl", "DISTROS") +load("//private/util:deb.bzl", "deb") package(default_visibility = ["//visibility:public"]) @@ -30,9 +30,9 @@ package(default_visibility = ["//visibility:public"]) name = ("cc" if (not mode) else mode[1:]) + "_" + user + "_" + arch + "_" + distro, base = "//base" + (mode if mode else ":base") + "_" + user + "_" + arch + "_" + distro, tars = [ - deb_pkg(arch, distro, "libgomp1"), - deb_pkg(arch, distro, "libstdcpp6"), - deb_pkg(arch, distro, "libgcc-s1"), + deb.package(arch, distro, "libgomp1"), + deb.package(arch, distro, "libstdcpp6"), + deb.package(arch, distro, "libgcc-s1"), ], ) for mode in [ diff --git a/common/BUILD.bazel b/common/BUILD.bazel new file mode 100644 index 000000000..2c494e3b2 --- /dev/null +++ b/common/BUILD.bazel @@ -0,0 +1,162 @@ +load("@aspect_bazel_lib//lib:tar.bzl", "tar") +load("@rules_distroless//distroless:defs.bzl", "cacerts", "group", "home", "locale", "os_release", "passwd") +load("//:checksums.bzl", "ARCHITECTURES", "VERSIONS") +load("//base:distro.bzl", "DISTROS") +load("//private/util:deb.bzl", "deb") +load(":variables.bzl", "MTIME", "NOBODY", "NONROOT", "OS_RELEASE", "ROOT", "quote") + +package(default_visibility = ["//visibility:public"]) + +tar( + name = "rootfs", + srcs = [], + args = [ + "--format", + "gnutar", + ], + compress = "gzip", + mtree = ["./ type=dir uid=0 gid=0 time=0.0"], +) + +tar( + name = "tmp", + srcs = [], + # original tmp.tar was created on a gnutar, mimic that. + args = [ + "--format", + "gnutar", + ], + compress = "gzip", + mtree = ["./tmp gname=root uname=root time=1501783453.0 mode=1777 gid=0 uid=0 type=dir"], +) + +[ + os_release( + name = "os_release_%s" % dist, + content = { + key: quote(value.format( + CODENAME = codename, + VERSION = version, + )) + for (key, value) in OS_RELEASE.items() + }, + time = MTIME, + ) + for (dist, codename, version) in VERSIONS +] + +[ + locale( + name = "locale_%s_%s" % (distro, arch), + # From Debian 12 the C.UTF-8 locale has been renamed into C.utf8: + # https://metadata.ftp-master.debian.org/changelogs//main/g/glibc/glibc_2.36-9+deb12u1_changelog + # > * debian/debhelper.in/libc-bin.install, debian/rules.d/build.mk, + # > debian/rules: rename the C.UTF-8 locale into C.utf8 to match upstream + # > naming. + charset = "C.UTF-8" if distro == "debian11" else "C.utf8", + package = deb.data(arch, distro, "libc-bin"), + time = MTIME, + ) + for arch in ARCHITECTURES + for distro in DISTROS +] + +[ + cacerts( + name = "cacerts_%s_%s" % (distro, arch), + package = deb.data(arch, distro, "ca-certificates"), + time = MTIME, + ) + for arch in ARCHITECTURES + for distro in DISTROS +] + +# create /etc/group with the root, tty, and staff groups +group( + name = "group", + entries = [ + { + "name": "root", # root_group + "gid": ROOT, + "password": "x", + }, + { + "name": "nobody", # nobody_group + "gid": NOBODY, + "password": "x", + }, + { + "name": "tty", # tty_group + "gid": 5, + "password": "x", + }, + { + "name": "staff", # staff_group + "gid": 50, + "password": "x", + }, + { + "name": "nonroot", # nonroot_group + "gid": NONROOT, + "password": "x", + }, + ], + time = MTIME, +) + +passwd( + name = "passwd", + entries = [ + { + "gecos": ["root"], + "gid": ROOT, + "shell": "/sbin/nologin", + "home": "/root", + "uid": ROOT, + "password": "x", + "username": "root", + }, + { + "gecos": ["nobody"], + "gid": NOBODY, + "home": "/nonexistent", + "shell": "/sbin/nologin", + "uid": NOBODY, + "password": "x", + "username": "nobody", + }, + { + "gecos": ["nonroot"], + "gid": NONROOT, + "home": "/home/nonroot", + "shell": "/sbin/nologin", + "uid": NONROOT, + "password": "x", + "username": "nonroot", + }, + ], +) + +home( + name = "home", + dirs = [ + { + "home": "/root", + "uid": ROOT, + "gid": ROOT, + "mode": 700, + }, + { + "home": "/home", + "uid": NONROOT, + "gid": NONROOT, + "mode": 755, + }, + { + "home": "/home/nonroot", + "uid": NONROOT, + "gid": NONROOT, + "mode": 700, + }, + ], +) diff --git a/common/variables.bzl b/common/variables.bzl new file mode 100644 index 000000000..767bd8a1f --- /dev/null +++ b/common/variables.bzl @@ -0,0 +1,22 @@ +"common variables" + +def quote(str): + return '''"{}"'''.format(str) + +OS_RELEASE = dict( + PRETTY_NAME = "Distroless", + NAME = "Debian GNU/Linux", + ID = "debian", + VERSION_ID = "{VERSION}", + VERSION = "Debian GNU/Linux {VERSION} ({CODENAME})", + HOME_URL = "https://github.com/GoogleContainerTools/distroless", + SUPPORT_URL = "https://github.com/GoogleContainerTools/distroless/blob/master/README.md", + BUG_REPORT_URL = "https://github.com/GoogleContainerTools/distroless/issues/new", +) + +NOBODY = 65534 +NONROOT = 65532 +ROOT = 0 + +# TODO: this should be 0, but for now we'll use this to minimize diff. +MTIME = "946684800" diff --git a/examples/nonroot/BUILD b/examples/nonroot/BUILD index 007765549..cf1f76798 100644 --- a/examples/nonroot/BUILD +++ b/examples/nonroot/BUILD @@ -2,39 +2,46 @@ # reference only. Note that repo maintainers can freely change any part of the # repository code at any time. load("@container_structure_test//:defs.bzl", "container_structure_test") -load("@io_bazel_rules_docker//contrib:passwd.bzl", "passwd_entry", "passwd_file") load("@io_bazel_rules_go//go:def.bzl", "go_binary") +load("@rules_distroless//distroless:defs.bzl", "home", "passwd") load("@rules_oci//oci:defs.bzl", "oci_image") load("@rules_pkg//:pkg.bzl", "pkg_tar") load("//base:distro.bzl", "DISTROS") -# Create a passwd file with a nonroot user and uid. -passwd_entry( - name = "nonroot_user", - info = "nonroot", - uid = 1002, - username = "nonroot", -) - -passwd_file( +# Create a passwd file and home directory with a nonroot user and uid. +passwd( name = "passwd", entries = [ - ":nonroot_user", + { + "gecos": ["nonroot"], + "gid": 1000, + "home": "/home", + "shell": "/bin/bash", + "uid": 1002, + "username": "nonroot", + }, ], ) -pkg_tar( - name = "passwd_tar", - srcs = [":passwd"], - mode = "0644", - package_dir = "etc", +home( + name = "home", + dirs = [ + { + "home": "/home", + "uid": 1002, + "gid": 1000, + }, + ], ) # Include it in our image as a tar. oci_image( name = "passwd_image", base = "//base:base_root_amd64_debian11", - tars = [":passwd_tar"], + tars = [ + ":passwd", + ":home", + ], user = "nonroot", visibility = ["//visibility:private"], ) diff --git a/experimental/python3/BUILD b/experimental/python3/BUILD index 12bd7f9c3..9d2b70abe 100644 --- a/experimental/python3/BUILD +++ b/experimental/python3/BUILD @@ -2,8 +2,9 @@ load("@container_structure_test//:defs.bzl", "container_structure_test") load("@rules_oci//oci:defs.bzl", "oci_image", "oci_image_index", "oci_tarball") load("@rules_pkg//:pkg.bzl", "pkg_tar") load("//:checksums.bzl", ARCHITECTURES = "BASE_ARCHITECTURES") -load("//base:base.bzl", "NONROOT", "deb_pkg") load("//base:distro.bzl", DISTROS = "LANGUAGE_DISTROS") +load("//common:variables.bzl", "NONROOT") +load("//private/util:deb.bzl", "deb") package(default_visibility = ["//visibility:public"]) @@ -49,33 +50,33 @@ DISTRO_VERSION = { # Use UTF-8 encoding for file system: match modern Linux env = {"LANG": "C.UTF-8"}, tars = [ - deb_pkg(arch, distro, "dash"), - deb_pkg(arch, distro, "libbz2-1.0"), - deb_pkg(arch, distro, "libc-bin"), # for ctypes.find_library - deb_pkg(arch, distro, "libdb5.3"), - deb_pkg(arch, distro, "libexpat1"), - deb_pkg(arch, distro, "liblzma5"), - deb_pkg(arch, distro, "libsqlite3-0"), - deb_pkg(arch, distro, "libuuid1"), - deb_pkg(arch, distro, "libncursesw6"), - deb_pkg(arch, distro, "libtinfo6"), - deb_pkg(arch, distro, "python3-distutils"), - deb_pkg(arch, distro, "zlib1g"), - deb_pkg(arch, distro, "libcom-err2"), - deb_pkg(arch, distro, "libcrypt1"), - deb_pkg(arch, distro, "libffi7"), - deb_pkg(arch, distro, "libgssapi-krb5-2"), - deb_pkg(arch, distro, "libk5crypto3"), - deb_pkg(arch, distro, "libkeyutils1"), - deb_pkg(arch, distro, "libkrb5-3"), - deb_pkg(arch, distro, "libkrb5support0"), - deb_pkg(arch, distro, "libmpdec3"), - deb_pkg(arch, distro, "libnsl2"), - deb_pkg(arch, distro, "libpython3.9-minimal"), - deb_pkg(arch, distro, "libpython3.9-stdlib"), - deb_pkg(arch, distro, "libreadline8"), - deb_pkg(arch, distro, "libtirpc3"), - deb_pkg(arch, distro, "python3.9-minimal"), + deb.package(arch, distro, "dash"), + deb.package(arch, distro, "libbz2-1.0"), + deb.package(arch, distro, "libc-bin"), # for ctypes.find_library + deb.package(arch, distro, "libdb5.3"), + deb.package(arch, distro, "libexpat1"), + deb.package(arch, distro, "liblzma5"), + deb.package(arch, distro, "libsqlite3-0"), + deb.package(arch, distro, "libuuid1"), + deb.package(arch, distro, "libncursesw6"), + deb.package(arch, distro, "libtinfo6"), + deb.package(arch, distro, "python3-distutils"), + deb.package(arch, distro, "zlib1g"), + deb.package(arch, distro, "libcom-err2"), + deb.package(arch, distro, "libcrypt1"), + deb.package(arch, distro, "libffi7"), + deb.package(arch, distro, "libgssapi-krb5-2"), + deb.package(arch, distro, "libk5crypto3"), + deb.package(arch, distro, "libkeyutils1"), + deb.package(arch, distro, "libkrb5-3"), + deb.package(arch, distro, "libkrb5support0"), + deb.package(arch, distro, "libmpdec3"), + deb.package(arch, distro, "libnsl2"), + deb.package(arch, distro, "libpython3.9-minimal"), + deb.package(arch, distro, "libpython3.9-stdlib"), + deb.package(arch, distro, "libreadline8"), + deb.package(arch, distro, "libtirpc3"), + deb.package(arch, distro, "python3.9-minimal"), "ld_so_" + arch + "_cache.tar", ":python_aliases_%s" % distro, ], diff --git a/java/BUILD b/java/BUILD index 5df11a769..ec675a9ad 100644 --- a/java/BUILD +++ b/java/BUILD @@ -3,11 +3,11 @@ load("@rules_oci//oci:defs.bzl", "oci_image", "oci_image_index") load("@rules_pkg//:pkg.bzl", "pkg_tar") load("//:debian_versions.bzl", DEBIAN_VERSIONS = "DEBIAN_PACKAGE_VERSIONS") load("//:java_archives.bzl", "JAVA_RELEASE_VERSIONS") -load("//base:base.bzl", "deb_pkg") load("//base:distro.bzl", "DISTROS") -load("//cacerts:java.bzl", "cacerts_java") load("//java:jre_ver.bzl", "jre_ver") load("//private/oci:defs.bzl", "java_image") +load("//private/util:deb.bzl", "deb") +load("//private/util:java_cacerts.bzl", "java_cacerts") package(default_visibility = ["//visibility:public"]) @@ -37,9 +37,9 @@ JAVA_VERSIONS_PER_DISTRO = [ ] [ - cacerts_java( + java_cacerts( name = "cacerts_java_" + arch + "_" + distro, - cacerts_tar = "//base:cacerts_" + arch + "_" + distro, + archive = "//common:cacerts_" + distro + "_" + arch, ) for distro in DISTROS for arch in JAVA_ARCHITECTURES @@ -52,7 +52,7 @@ JAVA_VERSIONS_PER_DISTRO = [ "/usr/bin/java": "/usr/lib/jvm/java-" + java_version + "-openjdk-" + arch + "/bin/java", }, deps = [ - deb_pkg( + deb.package( arch, distro, "openjdk-" + java_version + "-jre-headless", @@ -119,21 +119,21 @@ JAVA_VERSIONS_PER_DISTRO = [ base = ("//base:base_nossl" if (not ("debug" in mode)) else "//base:base_nossl_debug") + "_" + user + "_" + arch + "_" + distro, env = {"LANG": "C.UTF-8"}, tars = [ - deb_pkg(arch, distro, "zlib1g"), - deb_pkg(arch, distro, "libjpeg62-turbo"), - deb_pkg(arch, distro, "libpng16-16"), - deb_pkg(arch, distro, "liblcms2-2"), - deb_pkg(arch, distro, "libfreetype6"), - deb_pkg(arch, distro, "fonts-dejavu-core"), - deb_pkg(arch, distro, "fontconfig-config"), - deb_pkg(arch, distro, "libexpat1"), - deb_pkg(arch, distro, "libfontconfig1"), - deb_pkg(arch, distro, "libuuid1"), - deb_pkg(arch, distro, "libbrotli1"), - deb_pkg(arch, distro, "libcrypt1"), - deb_pkg(arch, distro, "libstdcpp6"), - deb_pkg(arch, distro, "libgcc-s1"), - "//locale:locale_" + arch + "_" + distro, + deb.package(arch, distro, "zlib1g"), + deb.package(arch, distro, "libjpeg62-turbo"), + deb.package(arch, distro, "libpng16-16"), + deb.package(arch, distro, "liblcms2-2"), + deb.package(arch, distro, "libfreetype6"), + deb.package(arch, distro, "fonts-dejavu-core"), + deb.package(arch, distro, "fontconfig-config"), + deb.package(arch, distro, "libexpat1"), + deb.package(arch, distro, "libfontconfig1"), + deb.package(arch, distro, "libuuid1"), + deb.package(arch, distro, "libbrotli1"), + deb.package(arch, distro, "libcrypt1"), + deb.package(arch, distro, "libstdcpp6"), + deb.package(arch, distro, "libgcc-s1"), + "//common:locale_" + distro + "_" + arch, ], ) for mode in [ @@ -161,11 +161,11 @@ DISTRO_SPECIFIC_LIBRARIES = { base = "java_build_base" + mode + "_" + user + "_" + arch + "_" + distro, env = {"LANG": "C.UTF-8"}, tars = [ - deb_pkg(arch, distro, "libharfbuzz0b"), - deb_pkg(arch, distro, "libgraphite2-3"), - deb_pkg(arch, distro, "libglib2.0-0"), + deb.package(arch, distro, "libharfbuzz0b"), + deb.package(arch, distro, "libgraphite2-3"), + deb.package(arch, distro, "libglib2.0-0"), ":cacerts_java_" + arch + "_" + distro, - ] + [deb_pkg(arch, distro, library) for library in DISTRO_SPECIFIC_LIBRARIES[distro]], + ] + [deb.package(arch, distro, library) for library in DISTRO_SPECIFIC_LIBRARIES[distro]], ) for mode in [ "", @@ -239,7 +239,7 @@ DISTRO_SPECIFIC_LIBRARIES = { }, tars = [ ":openjdk_jre_headless_" + java_version + "_" + arch + "_" + distro, - deb_pkg( + deb.package( arch, distro, "openjdk-" + java_version + "-jdk-headless", diff --git a/locale/BUILD b/locale/BUILD deleted file mode 100644 index b233f7997..000000000 --- a/locale/BUILD +++ /dev/null @@ -1,16 +0,0 @@ -load("//base:distro.bzl", "DISTROS") -load("//base:base.bzl", "deb_file") -load("//:checksums.bzl", "ARCHITECTURES") -load(":locale.bzl", "locale") - -package(default_visibility = ["//:__subpackages__"]) - -[ - locale( - name = "locale_" + arch + "_" + distro, - deb_file = deb_file(arch, distro, "libc-bin"), - distro = distro, - ) - for arch in ARCHITECTURES - for distro in DISTROS -] diff --git a/locale/locale.bzl b/locale/locale.bzl deleted file mode 100644 index b7eefc568..000000000 --- a/locale/locale.bzl +++ /dev/null @@ -1,61 +0,0 @@ -"""A rule to unpack minimal locales from the debian package.""" - -load("@rules_pkg//:providers.bzl", "PackageFilesInfo") -load("@rules_pkg//:pkg.bzl", "pkg_tar") - -def _impl(ctx): - # From Debian 12 the C.UTF-8 locale has been renamed into C.utf8: - # https://metadata.ftp-master.debian.org/changelogs//main/g/glibc/glibc_2.36-9+deb12u1_changelog - # > * debian/debhelper.in/libc-bin.install, debian/rules.d/build.mk, - # > debian/rules: rename the C.UTF-8 locale into C.utf8 to match upstream - # > naming. - cutf8 = "C.UTF-8" if ctx.attr.distro == "debian11" else "C.utf8" - locale = ctx.actions.declare_directory("%s/locale" % ctx.label.name) - copyright = ctx.actions.declare_file("%s/copyright" % ctx.label.name) - ctx.actions.run_shell( - inputs = [ctx.file.deb_file], - outputs = [locale, copyright], - arguments = [ - ctx.file.deb_file.path, - cutf8, - locale.path, - copyright.path, - ], - command = """ - set -o pipefail -o errexit -o nounset - tmp=$(mktemp -d) - tar -xf "$1" -C "$tmp" ./usr/lib/locale/$2 ./usr/share/doc/libc-bin/copyright - cp -r "$tmp/usr/lib/locale/$2/." $3 - mv "$tmp/usr/share/doc/libc-bin/copyright" $4 - """, - ) - - return [ - DefaultInfo(files = depset([locale, copyright])), - PackageFilesInfo( - dest_src_map = { - "/usr/lib/locale/%s" % cutf8: locale, - "/usr/share/doc/libc-bin/copyright": copyright, - }, - attributes = {"mode": "0644"}, - ), - ] - -_locale = rule( - attrs = { - "deb_file": attr.label( - allow_single_file = True, - mandatory = True, - ), - "distro": attr.string(), - }, - executable = False, - implementation = _impl, -) - -def locale(name, **kwargs): - _locale(name = "%s_locale" % name, **kwargs) - pkg_tar( - name = name, - srcs = ["%s_locale" % name], - ) diff --git a/os_release/BUILD b/os_release/BUILD deleted file mode 100644 index 9ea0ee63c..000000000 --- a/os_release/BUILD +++ /dev/null @@ -1,14 +0,0 @@ -#package(default_visibility = ["//:__subpackages__"]) -package(default_visibility = ["//visibility:public"]) - -load("//:checksums.bzl", "VERSIONS") -load(":os_release.bzl", "os_release") - -[ - os_release( - name = "os_release_" + distro, - codename = codename, - version = version, - ) - for (distro, codename, version) in VERSIONS -] diff --git a/os_release/os_release.bzl b/os_release/os_release.bzl deleted file mode 100644 index 8d00508cc..000000000 --- a/os_release/os_release.bzl +++ /dev/null @@ -1,41 +0,0 @@ -"""A rule to build os-release information for debian-distroless releases.""" - -load("@rules_pkg//:providers.bzl", "PackageFilesInfo") -load("@rules_pkg//:pkg.bzl", "pkg_tar") - -OS_RELEASE_TMPL = """\ -PRETTY_NAME="Distroless" -NAME="Debian GNU/Linux" -ID="debian" -VERSION_ID="{VERSION}" -VERSION="Debian GNU/Linux {VERSION} ({CODENAME})" -HOME_URL="https://github.com/GoogleContainerTools/distroless" -SUPPORT_URL="https://github.com/GoogleContainerTools/distroless/blob/master/README.md" -BUG_REPORT_URL="https://github.com/GoogleContainerTools/distroless/issues/new" -""" - -def _impl(ctx): - os_release = ctx.actions.declare_file("os_release_{}".format(ctx.label.name)) - ctx.actions.write( - os_release, - content = OS_RELEASE_TMPL.format( - VERSION = ctx.attr.version, - CODENAME = ctx.attr.codename, - ), - ) - return [ - DefaultInfo(files = depset([os_release])), - PackageFilesInfo(dest_src_map = {"/usr/lib/os-release": os_release}), - ] - -_os_release = rule( - attrs = { - "codename": attr.string(mandatory = True), - "version": attr.string(mandatory = True), - }, - implementation = _impl, -) - -def os_release(name, codename, version, **kwargs): - _os_release(name = "%s_generated" % name, codename = codename, version = version, **kwargs) - pkg_tar(name = name, srcs = ["%s_generated" % name], **kwargs) diff --git a/private/pkg/test/oci_image/BUILD.bazel b/private/pkg/test/oci_image/BUILD.bazel index 3f1ecf1f1..21a776356 100644 --- a/private/pkg/test/oci_image/BUILD.bazel +++ b/private/pkg/test/oci_image/BUILD.bazel @@ -1,14 +1,14 @@ load("@rules_oci//oci:defs.bzl", "oci_image", "oci_image_index") load("@aspect_bazel_lib//lib:write_source_files.bzl", "write_source_files") load("//private/pkg:oci_image_spdx.bzl", "oci_image_spdx") -load("//base:base.bzl", "deb_pkg") +load("//private/util:deb.bzl", "deb") oci_image( name = "image_arm64", architecture = "arm64", os = "linux", tars = [ - deb_pkg("arm64", "debian11", "base-files"), + deb.package("arm64", "debian11", "base-files"), ], ) @@ -22,7 +22,7 @@ oci_image( architecture = "amd64", os = "linux", tars = [ - deb_pkg("amd64", "debian11", "netbase"), + deb.package("amd64", "debian11", "netbase"), ], ) diff --git a/private/tools/diff.bash b/private/tools/diff.bash index 851b1770d..bf963870f 100755 --- a/private/tools/diff.bash +++ b/private/tools/diff.bash @@ -235,4 +235,4 @@ if [[ "${SET_GITHUB_OUTPUT}" == "1" ]]; then echo "changed_targets<> "$GITHUB_OUTPUT" cat "$CHANGED_IMAGES_FILE" >> "$GITHUB_OUTPUT" echo "EOF" >> "$GITHUB_OUTPUT" -fi \ No newline at end of file +fi diff --git a/private/util/deb.bzl b/private/util/deb.bzl new file mode 100644 index 000000000..8b2896281 --- /dev/null +++ b/private/util/deb.bzl @@ -0,0 +1,12 @@ +"utility functions for constructing debian package labels" + +def _package(arch, dist, package): + return "@{arch}_{dist}_{package}".format(arch = arch, dist = dist, package = package) + +def _data(arch, dist, package): + return "@{}//:data".format(_package(arch = arch, dist = dist, package = package)) + +deb = struct( + package = _package, + data = _data, +) diff --git a/private/util/extract.bzl b/private/util/extract.bzl new file mode 100644 index 000000000..4aee8db84 --- /dev/null +++ b/private/util/extract.bzl @@ -0,0 +1,36 @@ +"a utility that extracts files from tar" + +load("@aspect_bazel_lib//lib:tar.bzl", "tar_lib") + +def _tar_extract_file_impl(ctx): + bsdtar = ctx.toolchains[tar_lib.toolchain_type] + parts = ctx.attr.file.split("/") + output = ctx.actions.declare_file("/".join([ctx.label.name, parts[-1]])) + + args = ctx.actions.args() + args.add("--extract") + args.add("-C", "/".join([ctx.bin_dir.path, ctx.label.package, ctx.label.name])) + args.add("--file", ctx.file.archive) + args.add("--include", ctx.attr.file) + args.add("--strip-components={}".format(len(parts) - 1)) + + ctx.actions.run( + executable = bsdtar.tarinfo.binary, + inputs = [ctx.file.archive], + outputs = [output], + tools = bsdtar.default.files, + arguments = [args], + ) + + return [ + DefaultInfo(files = depset([output])), + ] + +tar_extract_file = rule( + implementation = _tar_extract_file_impl, + attrs = { + "archive": attr.label(allow_single_file = True, mandatory = True), + "file": attr.string(mandatory = True), + }, + toolchains = [tar_lib.toolchain_type], +) diff --git a/private/util/java_cacerts.bzl b/private/util/java_cacerts.bzl new file mode 100644 index 000000000..d88cb5496 --- /dev/null +++ b/private/util/java_cacerts.bzl @@ -0,0 +1,20 @@ +"java ca certificates" + +load("@rules_distroless//distroless:defs.bzl", "java_keystore") +load("//common:variables.bzl", "MTIME") +load(":extract.bzl", "tar_extract_file") + +def java_cacerts(name, archive): + tar_extract_file( + name = name + "_extract", + archive = archive, + file = "./etc/ssl/certs/ca-certificates.crt", + ) + + java_keystore( + name = name, + certificates = [ + ":" + name + "_extract", + ], + time = MTIME, + ) diff --git a/python3/BUILD b/python3/BUILD index b6f51dd76..d48de296d 100644 --- a/python3/BUILD +++ b/python3/BUILD @@ -2,7 +2,7 @@ load("@container_structure_test//:defs.bzl", "container_structure_test") load("@rules_oci//oci:defs.bzl", "oci_image", "oci_image_index") load("@rules_pkg//:pkg.bzl", "pkg_tar") load("//:checksums.bzl", ARCHITECTURES = "BASE_ARCHITECTURES") -load("//base:base.bzl", "deb_pkg") +load("//private/util:deb.bzl", "deb") package(default_visibility = ["//visibility:public"]) @@ -57,30 +57,30 @@ DISTRO_VERSION = { # Use UTF-8 encoding for file system: match modern Linux env = {"LANG": "C.UTF-8"}, tars = [ - deb_pkg(arch, distro, "libbz2-1.0"), - deb_pkg(arch, distro, "libdb5.3"), - deb_pkg(arch, distro, "libexpat1"), - deb_pkg(arch, distro, "liblzma5"), - deb_pkg(arch, distro, "libsqlite3-0"), - deb_pkg(arch, distro, "libuuid1"), - deb_pkg(arch, distro, "libncursesw6"), - deb_pkg(arch, distro, "libtinfo6"), - deb_pkg(arch, distro, "python3-distutils"), - deb_pkg(arch, distro, "zlib1g"), - deb_pkg(arch, distro, "libcom-err2"), - deb_pkg(arch, distro, "libcrypt1"), - deb_pkg(arch, distro, "libgssapi-krb5-2"), - deb_pkg(arch, distro, "libk5crypto3"), - deb_pkg(arch, distro, "libkeyutils1"), - deb_pkg(arch, distro, "libkrb5-3"), - deb_pkg(arch, distro, "libkrb5support0"), - deb_pkg(arch, distro, "libnsl2"), - deb_pkg(arch, distro, "libreadline8"), - deb_pkg(arch, distro, "libtirpc3"), - deb_pkg(arch, distro, "libffi8"), - deb_pkg(arch, distro, "libpython3.11-minimal"), - deb_pkg(arch, distro, "libpython3.11-stdlib"), - deb_pkg(arch, distro, "python3.11-minimal"), + deb.package(arch, distro, "libbz2-1.0"), + deb.package(arch, distro, "libdb5.3"), + deb.package(arch, distro, "libexpat1"), + deb.package(arch, distro, "liblzma5"), + deb.package(arch, distro, "libsqlite3-0"), + deb.package(arch, distro, "libuuid1"), + deb.package(arch, distro, "libncursesw6"), + deb.package(arch, distro, "libtinfo6"), + deb.package(arch, distro, "python3-distutils"), + deb.package(arch, distro, "zlib1g"), + deb.package(arch, distro, "libcom-err2"), + deb.package(arch, distro, "libcrypt1"), + deb.package(arch, distro, "libgssapi-krb5-2"), + deb.package(arch, distro, "libk5crypto3"), + deb.package(arch, distro, "libkeyutils1"), + deb.package(arch, distro, "libkrb5-3"), + deb.package(arch, distro, "libkrb5support0"), + deb.package(arch, distro, "libnsl2"), + deb.package(arch, distro, "libreadline8"), + deb.package(arch, distro, "libtirpc3"), + deb.package(arch, distro, "libffi8"), + deb.package(arch, distro, "libpython3.11-minimal"), + deb.package(arch, distro, "libpython3.11-stdlib"), + deb.package(arch, distro, "python3.11-minimal"), ":python_aliases_%s" % distro, ], )