create-certs.sh 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. #!/usr/bin/env bash
  2. # Copyright Materialize, Inc. and contributors. All rights reserved.
  3. #
  4. # Use of this software is governed by the Business Source License
  5. # included in the LICENSE file at the root of this repository.
  6. #
  7. # As of the Change Date specified in that file, in accordance with
  8. # the Business Source License, use of this software will be governed
  9. # by the Apache License, Version 2.0.
  10. # This code creates TLS certificates for the various TLS-enabled services that
  11. # appear throughout our mzcompose infrastructure. See test/kafka-auth for a
  12. # representative example.
  13. #
  14. # For each service, we generate:
  15. #
  16. # * A PEM-formatted certificate and key, signed by the "ca" CA, in the files
  17. # SERVICE.crt and SERVICE.key. The certificate is valid for the hostnames
  18. # `SERVICE` and `*.SERVICE.local`. The latter wildcard is useful when it's
  19. # necessary to run multiple copies of the service at different hostnames
  20. # using the same TLS certificate (e.g., `replica1.SERVICE.local` and
  21. # `replica2.SERVICE.local`). The `.local` suffix is required as TLS wildcard
  22. # certificates are not valid for top-level domains (e.g., `*.SERVICE`).
  23. # * A PKCS#12-formatted archive containing the above certificate and key in a
  24. # file named SERVICE.p12.
  25. #
  26. # For Java services like Kafka, we additionally generate:
  27. #
  28. # * A Java KeyStore named SERVICE.keystore.jks that contains ca.crt,
  29. # SERVICE.crt, and SERVICE.key.
  30. #
  31. # * A PEM-formatted certificate and key, signed by the "ca-selective" CA, in
  32. # the files materialized-SERVICE.crt and materialized-SERVICE.key.
  33. #
  34. # * A Java TrustStore named SERVICE.truststore.jks that contains ca.crt and
  35. # materialized-SERVICE.crt.
  36. #
  37. # The idea is that you configure services to use SERVICE.key as a client
  38. # certificate when communicating with other services, and to trust ca.crt
  39. # (or SERVICE.truststore.jks for Java services) when other services connect to it.
  40. # The certificates signed by "ca" are then useful when you want a certificate that
  41. # can connect to any other service.
  42. #
  43. # The certificates signed by "ca-selective" are useful when you want to provide
  44. # Materialize with a certificate that can talk to one service but not another. For
  45. # example, the materialize-kafka.key file enables communication with Kafka
  46. # but not the Schema Registry.
  47. set -euo pipefail
  48. export SSL_SECRET=mzmzmz
  49. mkdir secrets
  50. # Create CA
  51. openssl req \
  52. -x509 \
  53. -days 36500 \
  54. -newkey rsa:4096 \
  55. -keyout secrets/ca.key \
  56. -out secrets/ca.crt \
  57. -sha256 \
  58. -batch \
  59. -subj "/CN=MZ RSA CA" \
  60. -passin pass:$SSL_SECRET \
  61. -passout pass:$SSL_SECRET
  62. # Create an alternative CA, used for certain tests
  63. openssl req \
  64. -x509 \
  65. -days 36500 \
  66. -newkey rsa:4096 \
  67. -keyout secrets/ca-selective.key \
  68. -out secrets/ca-selective.crt \
  69. -sha256 \
  70. -batch \
  71. -subj "/CN=MZ RSA CA" \
  72. -passin pass:$SSL_SECRET \
  73. -passout pass:$SSL_SECRET
  74. # create_cert CLIENT-NAME CA-NAME COMMON-NAME
  75. create_cert() {
  76. local client_name=$1
  77. local ca_name=$2
  78. local common_name=$3
  79. # Create key & CSR.
  80. openssl req -nodes \
  81. -newkey rsa:2048 \
  82. -keyout secrets/"$client_name".key \
  83. -out tmp/"$client_name".csr \
  84. -sha256 \
  85. -batch \
  86. -subj "/CN=$common_name" \
  87. -addext "subjectAltName = DNS:$common_name, DNS:*.$common_name.local" \
  88. -passin pass:$SSL_SECRET \
  89. -passout pass:$SSL_SECRET \
  90. # Sign the CSR.
  91. openssl x509 -req \
  92. -CA secrets/"$ca_name".crt \
  93. -CAkey secrets/"$ca_name".key \
  94. -in tmp/"$client_name".csr \
  95. -out secrets/"$client_name".crt \
  96. -sha256 \
  97. -days 36500 \
  98. -CAcreateserial \
  99. -copy_extensions copy \
  100. -passin pass:$SSL_SECRET \
  101. # Export key and certificate as a PKCS#12 archive for import into JKSs.
  102. openssl pkcs12 \
  103. -export \
  104. -in secrets/"$client_name".crt \
  105. -name "$client_name" \
  106. -inkey secrets/"$client_name".key \
  107. -passin pass:$SSL_SECRET \
  108. -certfile secrets/"$ca_name".crt \
  109. -out tmp/"$client_name".p12 \
  110. -passout pass:$SSL_SECRET
  111. # Export key and certificate as a PKCS#12 archive with newer cipher
  112. # suites for use by OpenSSL v3+.
  113. openssl pkcs12 \
  114. -export \
  115. -keypbe AES-256-CBC \
  116. -certpbe AES-256-CBC \
  117. -in secrets/"$client_name".crt \
  118. -name "$client_name" \
  119. -inkey secrets/"$client_name".key \
  120. -passin pass:$SSL_SECRET \
  121. -certfile secrets/"$ca_name".crt \
  122. -out secrets/"$client_name".p12 \
  123. -passout pass:$SSL_SECRET
  124. }
  125. for i in materialized producer postgres certuser balancerd frontegg-mock sql-server
  126. do
  127. create_cert $i "ca" $i
  128. done
  129. for i in kafka kafka1 kafka2 schema-registry
  130. do
  131. create_cert $i "ca" $i
  132. create_cert "materialized-$i" "ca-selective" "materialized"
  133. # Create JKS
  134. keytool -importkeystore \
  135. -deststorepass $SSL_SECRET \
  136. -destkeypass $SSL_SECRET \
  137. -srcstorepass $SSL_SECRET \
  138. -destkeystore secrets/$i.keystore.jks \
  139. -srckeystore tmp/$i.p12 \
  140. -srcstoretype PKCS12
  141. # Import CA
  142. keytool \
  143. -alias CARoot \
  144. -import \
  145. -file secrets/ca.crt \
  146. -keystore secrets/$i.keystore.jks \
  147. -noprompt -storepass $SSL_SECRET -keypass $SSL_SECRET
  148. # Create truststore and import CA cert
  149. keytool \
  150. -keystore secrets/$i.truststore.jks \
  151. -alias CARoot \
  152. -import \
  153. -file secrets/ca.crt \
  154. -noprompt -storepass $SSL_SECRET -keypass $SSL_SECRET
  155. # Create truststore and import a cert using the alternative CA
  156. keytool \
  157. -keystore secrets/$i.truststore.jks \
  158. -alias Selective \
  159. -import \
  160. -file secrets/materialized-$i.crt \
  161. -noprompt -storepass $SSL_SECRET -keypass $SSL_SECRET
  162. done
  163. # Ensure files are readable for any user.
  164. chmod -R a+r secrets/
  165. # The PostgreSQL key must be only user accessible to satisfy PostgreSQL's
  166. # security checks.
  167. cp secrets/postgres.key secrets/postgres-world-readable.key
  168. chmod -R og-rwx secrets/postgres.key