This is an automated email from the ASF dual-hosted git repository. zrhoffman pushed a commit to branch 6.0.x in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git
commit 675de0795e06af90d9dacf3de6561d1a232fb1d4 Author: mattjackson220 <[email protected]> AuthorDate: Mon Sep 20 16:11:38 2021 -0600 Le regex fix (#6184) * Lets Encrypt updated for domains that don't contain the xmlid * updated changelog (cherry picked from commit 14d8d8ecc1660c183afc36678cc55d73dc9a9aa6) --- CHANGELOG.md | 1 + ...21090914220900_le_dns_challenge_xml_id.down.sql | 18 +++++++++ ...2021090914220900_le_dns_challenge_xml_id.up.sql | 18 +++++++++ .../traffic_ops_golang/deliveryservice/acme.go | 12 +++--- .../deliveryservice/acme_renew.go | 2 +- .../deliveryservice/letsencrypt_dns_challenge.go | 5 ++- .../core/ds/LetsEncryptDnsChallenge.java | 16 +++++++- .../core/ds/LetsEncryptDnsChallengeWatcher.java | 45 +++++++++++----------- 8 files changed, 84 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e01602..1fd6704 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -106,6 +106,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). - Fixed Federations IMS so TR federations watcher will get updates. - [#5129](https://github.com/apache/trafficcontrol/issues/5129) - Updated TM so that it returns a 404 if the endpoint is not supported. - Fixed Traffic Router crs/stats to prevent overflow and to correctly record the time used in averages. +- [#6093](https://github.com/apache/trafficcontrol/issues/6093) - Fixed Let's Encrypt to work for delivery services where the domain does not contain the XMLID. ### Changed - Migrated completely off of bower in favor of npm diff --git a/traffic_ops/app/db/migrations/2021090914220900_le_dns_challenge_xml_id.down.sql b/traffic_ops/app/db/migrations/2021090914220900_le_dns_challenge_xml_id.down.sql new file mode 100644 index 0000000..d2e7e61 --- /dev/null +++ b/traffic_ops/app/db/migrations/2021090914220900_le_dns_challenge_xml_id.down.sql @@ -0,0 +1,18 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to you 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. + */ + +ALTER TABLE dnschallenges DROP COLUMN IF EXISTS xml_id; diff --git a/traffic_ops/app/db/migrations/2021090914220900_le_dns_challenge_xml_id.up.sql b/traffic_ops/app/db/migrations/2021090914220900_le_dns_challenge_xml_id.up.sql new file mode 100644 index 0000000..64df6a0 --- /dev/null +++ b/traffic_ops/app/db/migrations/2021090914220900_le_dns_challenge_xml_id.up.sql @@ -0,0 +1,18 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to you 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. + */ + +ALTER TABLE dnschallenges ADD COLUMN xml_id text NOT NULL; diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/acme.go b/traffic_ops/traffic_ops_golang/deliveryservice/acme.go index 044a466..e89b8e6 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/acme.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/acme.go @@ -82,7 +82,8 @@ func (u *MyUser) GetPrivateKey() crypto.PrivateKey { // DNSProviderTrafficRouter is used in the lego library and contains a database in order to store the DNS challenges for ACME protocol. type DNSProviderTrafficRouter struct { - db *sqlx.DB + db *sqlx.DB + xmlId *string } // NewDNSProviderTrafficRouter returns a new DNSProviderTrafficRouter object. @@ -100,8 +101,8 @@ func (d *DNSProviderTrafficRouter) Present(domain, token, keyAuth string) error tx, err := d.db.Begin() fqdn, value := dns01.GetRecord(domain, keyAuth) - q := `INSERT INTO dnschallenges (fqdn, record) VALUES ($1, $2)` - response, err := tx.Exec(q, fqdn, value) + q := `INSERT INTO dnschallenges (fqdn, record, xml_id) VALUES ($1, $2, $3)` + response, err := tx.Exec(q, fqdn, value, *d.xmlId) tx.Commit() if err != nil { log.Errorf("Inserting dns txt record for fqdn '" + fqdn + "' record '" + value + "': " + err.Error()) @@ -439,7 +440,7 @@ func GetAcmeCertificates(cfg *config.Config, req tc.DeliveryServiceAcmeSSLKeysRe account = acmeAccount } - client, err := GetAcmeClient(account, userTx, db) + client, err := GetAcmeClient(account, userTx, db, req.Key) if err != nil { log.Errorf("acme: getting acme client for provider %s: %v", provider, err) api.CreateChangeLogRawTx(api.ApiChange, "DS: "+*req.DeliveryService+", ID: "+strconv.Itoa(dsID)+", ACTION: FAILED to add SSL keys with "+provider, currentUser, logTx) @@ -560,7 +561,7 @@ func GetAcmeAccountConfig(cfg *config.Config, acmeProvider string) *config.Confi } // GetAcmeClient uses the ACME account information in either cdn.conf or the database to create and register an ACME client. -func GetAcmeClient(acmeAccount *config.ConfigAcmeAccount, userTx *sql.Tx, db *sqlx.DB) (*lego.Client, error) { +func GetAcmeClient(acmeAccount *config.ConfigAcmeAccount, userTx *sql.Tx, db *sqlx.DB, xmlId *string) (*lego.Client, error) { if acmeAccount.UserEmail == "" { log.Errorf("An email address must be provided to use ACME with %v", acmeAccount.AcmeProvider) return nil, errors.New("An email address must be provided to use ACME with " + acmeAccount.AcmeProvider) @@ -610,6 +611,7 @@ func GetAcmeClient(acmeAccount *config.ConfigAcmeAccount, userTx *sql.Tx, db *sq client.Challenge.Remove(challenge.TLSALPN01) trafficRouterDns := NewDNSProviderTrafficRouter() trafficRouterDns.db = db + trafficRouterDns.xmlId = xmlId if err != nil { log.Errorf("Error creating Traffic Router DNS provider: %s", err.Error()) return nil, err diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/acme_renew.go b/traffic_ops/traffic_ops_golang/deliveryservice/acme_renew.go index 7b92526..eb7c78a 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/acme_renew.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/acme_renew.go @@ -145,7 +145,7 @@ func renewAcmeCerts(cfg *config.Config, dsName string, ctx context.Context, http return nil, errors.New("No acme account information in cdn.conf for " + keyObj.AuthType), http.StatusInternalServerError } - client, err := GetAcmeClient(acmeAccount, userTx, db) + client, err := GetAcmeClient(acmeAccount, userTx, db, &dsName) if err != nil { api.CreateChangeLogRawTx(api.ApiChange, "DS: "+dsName+", ID: "+strconv.Itoa(*dsID)+", ACTION: FAILED to add SSL keys with "+acmeAccount.AcmeProvider, currentUser, logTx) return nil, errors.New("getting acme client: " + err.Error()), http.StatusInternalServerError diff --git a/traffic_ops/traffic_ops_golang/deliveryservice/letsencrypt_dns_challenge.go b/traffic_ops/traffic_ops_golang/deliveryservice/letsencrypt_dns_challenge.go index 45fb560..a9af8cd 100644 --- a/traffic_ops/traffic_ops_golang/deliveryservice/letsencrypt_dns_challenge.go +++ b/traffic_ops/traffic_ops_golang/deliveryservice/letsencrypt_dns_challenge.go @@ -33,6 +33,7 @@ import ( type DnsRecord struct { Fqdn *string `json:"fqdn" db:"fqdn"` Record *string `json:"record" db:"record"` + XmlId *string `json:"xmlId" db:"xml_id"` } func GetDnsChallengeRecords(w http.ResponseWriter, r *http.Request) { @@ -43,7 +44,7 @@ func GetDnsChallengeRecords(w http.ResponseWriter, r *http.Request) { } defer inf.Close() - getQuery := `SELECT fqdn, record FROM dnschallenges` + getQuery := `SELECT fqdn, record, xml_id FROM dnschallenges` queryParamsToQueryCols := map[string]dbhelpers.WhereColumnInfo{ "fqdn": dbhelpers.WhereColumnInfo{Column: "fqdn"}, @@ -73,7 +74,7 @@ func getDnsRecords(tx *sqlx.Tx, getQuery string, queryValues map[string]interfac defer rows.Close() for rows.Next() { record := DnsRecord{} - if err := rows.Scan(&record.Fqdn, &record.Record); err != nil { + if err := rows.Scan(&record.Fqdn, &record.Record, &record.XmlId); err != nil { return nil, errors.New("scanning dns challenge records: " + err.Error()) } records = append(records, record) diff --git a/traffic_router/core/src/main/java/org/apache/traffic_control/traffic_router/core/ds/LetsEncryptDnsChallenge.java b/traffic_router/core/src/main/java/org/apache/traffic_control/traffic_router/core/ds/LetsEncryptDnsChallenge.java index 8261ba0..2260825 100644 --- a/traffic_router/core/src/main/java/org/apache/traffic_control/traffic_router/core/ds/LetsEncryptDnsChallenge.java +++ b/traffic_router/core/src/main/java/org/apache/traffic_control/traffic_router/core/ds/LetsEncryptDnsChallenge.java @@ -26,6 +26,9 @@ public class LetsEncryptDnsChallenge { @JsonProperty private String record; + @JsonProperty + private String xmlId; + public String getFqdn() { return fqdn; } @@ -42,6 +45,14 @@ public class LetsEncryptDnsChallenge { this.record = record; } + public String getXmlId() { + return xmlId; + } + + public void setXmlId(final String xmlId) { + this.xmlId = xmlId; + } + @Override public boolean equals(final Object o) { if (this == o) { @@ -52,11 +63,12 @@ public class LetsEncryptDnsChallenge { } final LetsEncryptDnsChallenge that = (LetsEncryptDnsChallenge) o; return fqdn.equals(that.fqdn) && - record.equals(that.record); + record.equals(that.record) && + xmlId.equals(that.xmlId); } @Override public int hashCode() { - return Objects.hash(fqdn, record); + return Objects.hash(fqdn, record, xmlId); } } diff --git a/traffic_router/core/src/main/java/org/apache/traffic_control/traffic_router/core/ds/LetsEncryptDnsChallengeWatcher.java b/traffic_router/core/src/main/java/org/apache/traffic_control/traffic_router/core/ds/LetsEncryptDnsChallengeWatcher.java index 957bf06..5ebc89c 100644 --- a/traffic_router/core/src/main/java/org/apache/traffic_control/traffic_router/core/ds/LetsEncryptDnsChallengeWatcher.java +++ b/traffic_router/core/src/main/java/org/apache/traffic_control/traffic_router/core/ds/LetsEncryptDnsChallengeWatcher.java @@ -31,6 +31,7 @@ import org.apache.log4j.Logger; import java.io.*; import java.time.Instant; import java.util.HashMap; +import java.util.Iterator; import java.util.List; public class LetsEncryptDnsChallengeWatcher extends AbstractResourceWatcher { @@ -57,35 +58,33 @@ public class LetsEncryptDnsChallengeWatcher extends AbstractResourceWatcher { challengeList.forEach(challenge -> { - final StringBuilder sb = new StringBuilder(); - sb.append(challenge.getFqdn()); - if (!challenge.getFqdn().endsWith(".")) { - sb.append('.'); + final ObjectNode deliveryServiceConfig = (ObjectNode) deliveryServicesNode.get(challenge.getXmlId()); + if (deliveryServiceConfig == null) { + LOGGER.error("finding deliveryservice in cr-config for " + challenge.getXmlId()); + return; } - final String challengeDomain = sb.toString(); - final String fqdn = challengeDomain.substring(0, challengeDomain.length() - 1).replace("_acme-challenge.", ""); - - ObjectNode deliveryServiceConfig = null; - String dsLabel = ""; - final StringBuilder nameSb = new StringBuilder(); - nameSb.append("_acme-challenge"); - for (final String label : fqdn.split("\\.")) { - deliveryServiceConfig = (ObjectNode) deliveryServicesNode.get(label); - if (deliveryServiceConfig != null) { - dsLabel = label; - break; - } else { - nameSb.append('.'); - nameSb.append(label); - } + + String staticEntryString = challenge.getFqdn(); + final ArrayNode domains = (ArrayNode) deliveryServiceConfig.get("domains"); + if (domains == null || domains.size() == 0) { + LOGGER.error("no domains found in cr-config for deliveryservice " + challenge.getXmlId()); + return; + } + + final Iterator<JsonNode> domainIter = domains.iterator(); + while(domainIter.hasNext()) { + final JsonNode domainNode = domainIter.next(); + staticEntryString = staticEntryString.replace(domainNode.asText() + ".", ""); } - final String name = nameSb.toString(); + if (staticEntryString.endsWith(".")) { + staticEntryString = staticEntryString.substring(0, staticEntryString.length() - 1); + } - final ArrayNode staticDnsEntriesNode = updateStaticEntries(challenge, name, mapper, deliveryServiceConfig); + final ArrayNode staticDnsEntriesNode = updateStaticEntries(challenge, staticEntryString, mapper, deliveryServiceConfig); deliveryServiceConfig.set("staticDnsEntries", staticDnsEntriesNode); - deliveryServicesNode.set(dsLabel, deliveryServiceConfig); + deliveryServicesNode.set(challenge.getXmlId(), deliveryServiceConfig); });
