-
Notifications
You must be signed in to change notification settings - Fork 37
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
576 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
|
||
// Parts taken from https://github.com/openjdk/jdk17u-dev/blob/a028120220f6fd28e39fe0f6190eb1f5da6a788d/make/jdk/src/classes/build/tools/generatecacerts/GenerateCacerts.java | ||
// https://github.com/GoogleContainerTools/distroless/tree/b1e2203eceb9cc91de0500d71c648e346e1d7b89/cacerts/jksutil | ||
import java.io.DataOutputStream; | ||
import java.io.FileOutputStream; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.OutputStream; | ||
import java.io.UnsupportedEncodingException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.security.DigestOutputStream; | ||
import java.security.MessageDigest; | ||
import java.security.NoSuchAlgorithmException; | ||
import java.security.cert.Certificate; | ||
import java.security.cert.CertificateException; | ||
import java.security.cert.CertificateFactory; | ||
import java.security.cert.X509Certificate; | ||
import java.util.Arrays; | ||
import java.util.HashMap; | ||
import java.util.Map.Entry; | ||
|
||
import javax.security.auth.x500.X500Principal; | ||
|
||
/** | ||
* Generate cacerts | ||
*/ | ||
class JavaKeyStore { | ||
|
||
private static final int MAGIC = 0xfeedfeed; | ||
private static final int VERSION = 0x02; | ||
private static final int TRUSTED_CERT_TAG = 0x02; | ||
private static final char[] PASSWORD = "changeit".toCharArray(); | ||
private static final String SALT = "Mighty Aphrodite"; | ||
|
||
public static void main(String[] args) throws Exception { | ||
try (FileOutputStream output = new FileOutputStream(args[0])) { | ||
store(output, Arrays.copyOfRange(args, 1, args.length)); | ||
} | ||
} | ||
|
||
public static void store(OutputStream stream, String[] entries) | ||
throws IOException, NoSuchAlgorithmException, CertificateException { | ||
byte[] encoded; // the certificate encoding | ||
CertificateFactory cf = CertificateFactory.getInstance("X509"); | ||
|
||
MessageDigest md = getPreKeyedHash(PASSWORD); | ||
DataOutputStream dos = new DataOutputStream(new DigestOutputStream(stream, md)); | ||
|
||
HashMap<String, X509Certificate> certs = new HashMap<String, X509Certificate>(); | ||
|
||
for (String entry : entries) { | ||
try (InputStream fis = Files.newInputStream(Path.of(entry))) { | ||
for (Certificate rcert : cf.generateCertificates(fis)) { | ||
X509Certificate cert = (X509Certificate) rcert; | ||
String alias = cert.getSubjectX500Principal().getName(X500Principal.CANONICAL); | ||
certs.put(alias, cert); | ||
} | ||
} | ||
} | ||
|
||
dos.writeInt(MAGIC); | ||
dos.writeInt(VERSION); | ||
dos.writeInt(certs.size()); | ||
|
||
for (Entry<String, X509Certificate> entry : certs.entrySet()) { | ||
|
||
X509Certificate cert = entry.getValue(); | ||
String alias = entry.getKey(); | ||
|
||
dos.writeInt(TRUSTED_CERT_TAG); | ||
|
||
// Write the alias | ||
dos.writeUTF(alias); | ||
|
||
// Write the (entry creation) date, which is notBefore of the cert | ||
dos.writeLong(cert.getNotBefore().getTime()); | ||
|
||
// Write the trusted certificate | ||
encoded = cert.getEncoded(); | ||
dos.writeUTF(cert.getType()); | ||
dos.writeInt(encoded.length); | ||
dos.write(encoded); | ||
} | ||
|
||
/* | ||
* Write the keyed hash which is used to detect tampering with | ||
* the keystore (such as deleting or modifying key or | ||
* certificate entries). | ||
*/ | ||
byte[] digest = md.digest(); | ||
|
||
dos.write(digest); | ||
dos.flush(); | ||
} | ||
|
||
private static MessageDigest getPreKeyedHash(char[] password) | ||
throws NoSuchAlgorithmException, UnsupportedEncodingException { | ||
|
||
MessageDigest md = MessageDigest.getInstance("SHA"); | ||
byte[] passwdBytes = convertToBytes(password); | ||
md.update(passwdBytes); | ||
Arrays.fill(passwdBytes, (byte) 0x00); | ||
md.update(SALT.getBytes("UTF8")); | ||
return md; | ||
} | ||
|
||
private static byte[] convertToBytes(char[] password) { | ||
int i, j; | ||
byte[] passwdBytes = new byte[password.length * 2]; | ||
for (i = 0, j = 0; i < password.length; i++) { | ||
passwdBytes[j++] = (byte) (password[i] >> 8); | ||
passwdBytes[j++] = (byte) password[i]; | ||
} | ||
return passwdBytes; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
"jks" | ||
|
||
load(":tar.bzl", "tar_lib") | ||
|
||
_DOC = """Create a java keystore (database) of cryptographic keys, X.509 certificate chains, and trusted certificates. | ||
Currently only public X.509 are supported as part of the PUBLIC API contract. | ||
""" | ||
|
||
def _java_keystore_impl(ctx): | ||
jks = ctx.actions.declare_file(ctx.attr.name + ".jks") | ||
|
||
args = ctx.actions.args() | ||
args.add(jks) | ||
args.add_all(ctx.files.certificates) | ||
|
||
ctx.actions.run( | ||
executable = ctx.executable._java_keystore, | ||
inputs = ctx.files.certificates, | ||
outputs = [jks], | ||
arguments = [args], | ||
) | ||
|
||
output = ctx.actions.declare_file(ctx.attr.name + ".tar.gz") | ||
mtree = tar_lib.create_mtree(ctx) | ||
mtree.add_file_with_parents("/etc/ssl/certs/java/cacerts", jks) | ||
mtree.build(output = output, mnemonic = "JavaKeyStore", inputs = [jks]) | ||
|
||
return [ | ||
DefaultInfo(files = depset([output])), | ||
OutputGroupInfo( | ||
jks = depset([jks]), | ||
), | ||
] | ||
|
||
java_keystore = rule( | ||
doc = _DOC, | ||
attrs = { | ||
"_java_keystore": attr.label( | ||
executable = True, | ||
cfg = "exec", | ||
default = ":keystore_binary", | ||
), | ||
"certificates": attr.label_list( | ||
allow_files = True, | ||
mandatory = True, | ||
allow_empty = False, | ||
), | ||
}, | ||
implementation = _java_keystore_impl, | ||
toolchains = [ | ||
tar_lib.TOOLCHAIN_TYPE, | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
load("//distroless:defs.bzl", "java_keystore") | ||
load("//distroless/tests:asserts.bzl", "assert_jks_listing", "assert_tar_listing") | ||
|
||
java_keystore( | ||
name = "java_keystore", | ||
certificates = [ | ||
# asserting that we support both bundle x509 certs | ||
# and single x509 certs | ||
"amazon.crt", | ||
"bundle.crt", | ||
], | ||
) | ||
|
||
filegroup( | ||
name = "java_keystore_jks", | ||
srcs = [":java_keystore"], | ||
output_group = "jks", | ||
) | ||
|
||
assert_jks_listing( | ||
name = "test_java_keystore_jks", | ||
actual = "java_keystore_jks", | ||
expected = "expected.jks.output", | ||
) | ||
|
||
assert_tar_listing( | ||
name = "test_java_keystore", | ||
actual = "java_keystore", | ||
expected = """\ | ||
#mtree | ||
./etc time=1672560000.0 mode=755 gid=0 uid=0 type=dir | ||
./etc/ssl time=1672560000.0 mode=755 gid=0 uid=0 type=dir | ||
./etc/ssl/certs time=1672560000.0 mode=755 gid=0 uid=0 type=dir | ||
./etc/ssl/certs/java time=1672560000.0 mode=755 gid=0 uid=0 type=dir | ||
./etc/ssl/certs/java/cacerts nlink=0 time=1672560000.0 mode=755 gid=0 uid=0 type=file size=5349 cksum=3752477219 sha1digest=015078faa5537fcabb6c7e73fe2dedf8241b106d | ||
""", | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
-----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----- |
Oops, something went wrong.