Skip to content

Commit 26ad8ee

Browse files
tmshortclaude
andcommitted
Replace generated mozilla_data.go with go:embed + runtime parsing
Embed mozilla_data.json and parse it at init() time using the existing cipherSuiteId()/curveId() helpers. Unsupported ciphers are skipped and recorded in skippedCiphers, validated by TestNoSkippedCiphers. Simplify update-tls-profiles.sh to a curl download and drop the gojq dependency. When the profile changes, `make verify` will show a diff of the profile. The build will still complete using the old data. The updated profile will need to be commited in order for it to be included in the build. Remove gojq from bingo. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Todd Short <tshort@redhat.com>
1 parent b6dfd40 commit 26ad8ee

File tree

9 files changed

+171
-198
lines changed

9 files changed

+171
-198
lines changed

.bingo/Variables.mk

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,6 @@ $(CRD_REF_DOCS): $(BINGO_DIR)/crd-ref-docs.mod
4747
@echo "(re)installing $(GOBIN)/crd-ref-docs-v0.3.0"
4848
@cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=crd-ref-docs.mod -o=$(GOBIN)/crd-ref-docs-v0.3.0 "github.com/elastic/crd-ref-docs"
4949

50-
GOJQ := $(GOBIN)/gojq-v0.12.17
51-
$(GOJQ): $(BINGO_DIR)/gojq.mod
52-
@# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies.
53-
@echo "(re)installing $(GOBIN)/gojq-v0.12.17"
54-
@cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=gojq.mod -o=$(GOBIN)/gojq-v0.12.17 "github.com/itchyny/gojq/cmd/gojq"
55-
5650
GOLANGCI_LINT := $(GOBIN)/golangci-lint-v2.8.0
5751
$(GOLANGCI_LINT): $(BINGO_DIR)/golangci-lint.mod
5852
@# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies.

.bingo/gojq.mod

Lines changed: 0 additions & 5 deletions
This file was deleted.

.bingo/gojq.sum

Lines changed: 0 additions & 17 deletions
This file was deleted.

.bingo/variables.env

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ CRD_DIFF="${GOBIN}/crd-diff-v0.5.1-0.20260309184313-54162f2e3097"
1818

1919
CRD_REF_DOCS="${GOBIN}/crd-ref-docs-v0.3.0"
2020

21-
GOJQ="${GOBIN}/gojq-v0.12.17"
22-
2321
GOLANGCI_LINT="${GOBIN}/golangci-lint-v2.8.0"
2422

2523
GORELEASER="${GOBIN}/goreleaser-v2.11.2"

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,8 @@ fmt: $(YAMLFMT) #EXHELP Formats code
221221
$(YAMLFMT) -gitignore_excludes testdata
222222

223223
.PHONY: update-tls-profiles
224-
update-tls-profiles: $(GOJQ) #EXHELP Update TLS profiles from the Mozilla wiki
225-
env JQ=$(GOJQ) hack/tools/update-tls-profiles.sh
224+
update-tls-profiles: #EXHELP Update TLS profiles from the Mozilla wiki
225+
hack/tools/update-tls-profiles.sh
226226

227227
.PHONY: update-registryv1-bundle-schema
228228
update-registryv1-bundle-schema: #EXHELP Update registry+v1 bundle configuration JSON schema

hack/tools/update-tls-profiles.sh

Lines changed: 2 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -2,131 +2,10 @@
22

33
set -e
44

5-
if [ -z "${JQ}" ]; then
6-
echo "JQ not defined"
7-
exit 1
8-
fi
9-
10-
OUTPUT=internal/shared/util/tlsprofiles/mozilla_data.go
5+
OUTPUT=internal/shared/util/tlsprofiles/mozilla_data.json
116
INPUT=https://ssl-config.mozilla.org/guidelines/latest.json
127

13-
TMPFILE="$(mktemp)"
14-
trap 'rm -rf "$TMPFILE"' EXIT
15-
16-
if ! curl -L -s -f "${INPUT}" > "${TMPFILE}"; then
8+
if ! curl -L -s -f "${INPUT}" -o "${OUTPUT}"; then
179
echo "ERROR: Failed to download ${INPUT} (HTTP error or connection failure)" >&2
1810
exit 1
1911
fi
20-
21-
if ! ${JQ} empty "${TMPFILE}" 2>/dev/null; then
22-
echo "ERROR: Downloaded data from ${INPUT} is not valid JSON" >&2
23-
exit 1
24-
fi
25-
26-
# Extract stored version from current output file (may be empty on first run)
27-
STORED_VERSION=$(grep '^// DATA VERSION:' "${OUTPUT}" 2>/dev/null | awk '{print $4}' || true)
28-
29-
# Extract version from downloaded JSON and fail early if missing
30-
NEW_VERSION=$(${JQ} -r '.version' "${TMPFILE}")
31-
if [ -z "${NEW_VERSION}" ] || [ "${NEW_VERSION}" = "null" ]; then
32-
echo "ERROR: Could not read .version from ${INPUT}" >&2
33-
exit 1
34-
fi
35-
36-
if [ "${NEW_VERSION}" = "${STORED_VERSION}" ]; then
37-
echo "Mozilla TLS data is already at version ${NEW_VERSION}, skipping regeneration."
38-
exit 0
39-
fi
40-
echo "Updating Mozilla TLS data from version ${STORED_VERSION:-unknown} to ${NEW_VERSION}"
41-
42-
cat > "${OUTPUT}" <<EOF
43-
package tlsprofiles
44-
45-
// DO NOT EDIT, GENERATED BY ${0}
46-
// DATA SOURCE: ${INPUT}
47-
// DATA VERSION: ${NEW_VERSION}
48-
49-
import (
50-
"crypto/tls"
51-
)
52-
EOF
53-
54-
function generate_profile {
55-
local profile="${1}"
56-
57-
# Validate the profile key exists before writing any output
58-
local exists
59-
exists=$(${JQ} -r ".configurations | has(\"${profile}\")" "${TMPFILE}")
60-
if [ "${exists}" != "true" ]; then
61-
echo "ERROR: Profile '${profile}' not found in ${INPUT} (version ${NEW_VERSION})" >&2
62-
echo "Available profiles: $(${JQ} -r '.configurations | keys | join(", ")' "${TMPFILE}")" >&2
63-
exit 1
64-
fi
65-
66-
# Validate tls_versions is a non-empty array with a non-null first entry
67-
if ! ${JQ} -e ".configurations.${profile}.tls_versions | type == \"array\" and length > 0 and .[0] != null" "${TMPFILE}" >/dev/null; then
68-
echo "ERROR: Missing or empty .configurations.${profile}.tls_versions[0] in ${INPUT}" >&2
69-
exit 1
70-
fi
71-
72-
# Validate that at least one cipher is present across ciphersuites and ciphers.iana
73-
# (modern has only ciphersuites; intermediate has both; either alone is valid)
74-
local cipher_count
75-
cipher_count=$(${JQ} -r "
76-
[
77-
(.configurations.${profile}.ciphersuites // []),
78-
(.configurations.${profile}.ciphers.iana // [])
79-
] | add | length" "${TMPFILE}")
80-
if [ "${cipher_count}" -eq 0 ] 2>/dev/null; then
81-
echo "ERROR: Profile '${profile}' has no ciphers in ciphersuites or ciphers.iana" >&2
82-
exit 1
83-
fi
84-
85-
# Validate tls_curves is non-empty
86-
local curve_count
87-
curve_count=$(${JQ} -r ".configurations.${profile}.tls_curves | length" "${TMPFILE}")
88-
if [ "${curve_count}" -eq 0 ] 2>/dev/null; then
89-
echo "ERROR: Profile '${profile}' has no entries in tls_curves" >&2
90-
exit 1
91-
fi
92-
93-
cat >> "${OUTPUT}" <<EOF
94-
95-
var ${profile}TLSProfile = tlsProfile{
96-
ciphers: cipherSlice{
97-
cipherNums: []uint16{
98-
EOF
99-
100-
${JQ} -r "(.configurations.${profile}.ciphersuites // [])[] | . |= \"tls.\" + . + \",\"" "${TMPFILE}" >> "${OUTPUT}"
101-
${JQ} -r "(.configurations.${profile}.ciphers.iana // [])[] | . |= \"tls.\" + . + \",\"" "${TMPFILE}" >> "${OUTPUT}"
102-
103-
cat >> "${OUTPUT}" <<EOF
104-
},
105-
},
106-
curves: curveSlice{
107-
curveNums: []tls.CurveID{
108-
EOF
109-
110-
${JQ} -r ".configurations.${profile}.tls_curves[] | . |= . + \",\"" "${TMPFILE}" >> "${OUTPUT}"
111-
112-
version=$(${JQ} -r ".configurations.${profile}.tls_versions[0]" "${TMPFILE}")
113-
version=${version/TLSv1./tls.VersionTLS1}
114-
version=${version/TLSv1/tls.VersionTLS10}
115-
116-
cat >> "${OUTPUT}" <<EOF
117-
},
118-
},
119-
minTLSVersion: ${version},
120-
}
121-
EOF
122-
}
123-
124-
generate_profile "modern"
125-
generate_profile "intermediate"
126-
127-
# Remove unsupported ciphers from Go's crypto/tls package
128-
sed -i.bak '/TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384/d; /TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384/d; /TLS_RSA_WITH_AES_256_CBC_SHA256/d' "${OUTPUT}"
129-
rm -f "${OUTPUT}.bak"
130-
131-
# Make go happy
132-
go fmt "${OUTPUT}"
Lines changed: 88 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,98 @@
11
package tlsprofiles
22

3-
// DO NOT EDIT, GENERATED BY hack/tools/update-tls-profiles.sh
4-
// DATA SOURCE: https://ssl-config.mozilla.org/guidelines/latest.json
5-
// DATA VERSION: 6
3+
// This file embeds the Mozilla SSL/TLS Configuration Guidelines JSON and parses
4+
// it at init() time to populate the modern and intermediate TLS profiles.
5+
// Run `make update-tls-profiles` to refresh mozilla_data.json from the upstream spec.
66

77
import (
88
"crypto/tls"
9+
_ "embed"
10+
"encoding/json"
11+
"fmt"
912
)
1013

11-
var modernTLSProfile = tlsProfile{
12-
ciphers: cipherSlice{
13-
cipherNums: []uint16{
14-
tls.TLS_AES_128_GCM_SHA256,
15-
tls.TLS_AES_256_GCM_SHA384,
16-
tls.TLS_CHACHA20_POLY1305_SHA256,
17-
},
18-
},
19-
curves: curveSlice{
20-
curveNums: []tls.CurveID{
21-
X25519MLKEM768,
22-
X25519,
23-
prime256v1,
24-
secp384r1,
25-
},
26-
},
27-
minTLSVersion: tls.VersionTLS13,
14+
//go:embed mozilla_data.json
15+
var mozillaDataJSON []byte
16+
17+
// skippedCiphers records cipher names from mozilla_data.json that are not
18+
// supported by Go's crypto/tls and were omitted from the profiles.
19+
var skippedCiphers []string
20+
21+
var (
22+
modernTLSProfile tlsProfile
23+
intermediateTLSProfile tlsProfile
24+
)
25+
26+
type mozillaConfiguration struct {
27+
Ciphersuites []string `json:"ciphersuites"`
28+
Ciphers struct {
29+
IANA []string `json:"iana"`
30+
} `json:"ciphers"`
31+
TLSCurves []string `json:"tls_curves"`
32+
TLSVersions []string `json:"tls_versions"`
2833
}
2934

30-
var intermediateTLSProfile = tlsProfile{
31-
ciphers: cipherSlice{
32-
cipherNums: []uint16{
33-
tls.TLS_AES_128_GCM_SHA256,
34-
tls.TLS_AES_256_GCM_SHA384,
35-
tls.TLS_CHACHA20_POLY1305_SHA256,
36-
tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
37-
tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
38-
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
39-
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
40-
tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
41-
tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256,
42-
},
43-
},
44-
curves: curveSlice{
45-
curveNums: []tls.CurveID{
46-
X25519MLKEM768,
47-
X25519,
48-
prime256v1,
49-
secp384r1,
50-
},
51-
},
52-
minTLSVersion: tls.VersionTLS12,
35+
type mozillaSpec struct {
36+
Configurations map[string]mozillaConfiguration `json:"configurations"`
37+
}
38+
39+
func init() {
40+
var spec mozillaSpec
41+
if err := json.Unmarshal(mozillaDataJSON, &spec); err != nil {
42+
panic(fmt.Sprintf("tlsprofiles: failed to parse embedded mozilla_data.json: %v", err))
43+
}
44+
45+
for _, name := range []string{"modern", "intermediate"} {
46+
cfg, ok := spec.Configurations[name]
47+
if !ok {
48+
panic(fmt.Sprintf("tlsprofiles: profile %q not found in embedded mozilla_data.json", name))
49+
}
50+
51+
p, skipped := parseProfile(name, cfg)
52+
skippedCiphers = append(skippedCiphers, skipped...)
53+
54+
switch name {
55+
case "modern":
56+
modernTLSProfile = p
57+
case "intermediate":
58+
intermediateTLSProfile = p
59+
}
60+
}
61+
}
62+
63+
func parseProfile(name string, cfg mozillaConfiguration) (tlsProfile, []string) {
64+
var skipped []string
65+
var cipherNums []uint16
66+
for _, c := range append(cfg.Ciphersuites, cfg.Ciphers.IANA...) {
67+
id := cipherSuiteId(c)
68+
if id == 0 {
69+
skipped = append(skipped, c)
70+
continue
71+
}
72+
cipherNums = append(cipherNums, id)
73+
}
74+
75+
var curveNums []tls.CurveID
76+
for _, c := range cfg.TLSCurves {
77+
id := curveId(c)
78+
if id == 0 {
79+
continue
80+
}
81+
curveNums = append(curveNums, id)
82+
}
83+
84+
if len(cfg.TLSVersions) == 0 {
85+
panic(fmt.Sprintf("tlsprofiles: profile %q has no tls_versions in embedded mozilla_data.json", name))
86+
}
87+
88+
var version tlsVersion
89+
if err := version.Set(cfg.TLSVersions[0]); err != nil {
90+
panic(fmt.Sprintf("tlsprofiles: profile %q has unrecognized tls_versions[0] %q: %v", name, cfg.TLSVersions[0], err))
91+
}
92+
93+
return tlsProfile{
94+
ciphers: cipherSlice{cipherNums: cipherNums},
95+
curves: curveSlice{curveNums: curveNums},
96+
minTLSVersion: version,
97+
}, skipped
5398
}

0 commit comments

Comments
 (0)