HTTPS: одна кнопка «Сохранить» на раздел (перенаправление, доменное имя, адрес без порта)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q7eREaYwUt1i4fNLZcGnjn
This commit is contained in:
@@ -376,73 +376,73 @@ func registerHostname(mux *http.ServeMux, rc *RuntimeConfig) {
|
||||
http.Error(w, "method", http.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
raw := strings.NewReplacer(",", " ", ";", " ", "\n", " ", "\r", " ").Replace(r.FormValue("hostnames"))
|
||||
var names []string
|
||||
for _, f := range strings.Fields(raw) {
|
||||
f = strings.ToLower(strings.TrimSpace(f))
|
||||
f = strings.TrimPrefix(f, "https://")
|
||||
f = strings.TrimPrefix(f, "http://")
|
||||
if i := strings.IndexByte(f, '/'); i >= 0 {
|
||||
f = f[:i]
|
||||
}
|
||||
if h, _, err := net.SplitHostPort(f); err == nil {
|
||||
f = h
|
||||
}
|
||||
if f == "" {
|
||||
continue
|
||||
}
|
||||
if !validHostname(f) {
|
||||
setupFlash(w, r, "Доменное имя «"+f+"» задано неверно. Пример: m2m.corp.example.ru")
|
||||
return
|
||||
}
|
||||
names = append(names, f)
|
||||
}
|
||||
names = uniqStrings(names)
|
||||
// имя должно быть в DNS и указывать на этот сервер — иначе браузер всё равно не откроет bj по нему
|
||||
mine := map[string]bool{}
|
||||
for _, ip := range serverIPs() {
|
||||
mine[ip] = true
|
||||
}
|
||||
var resolved []string
|
||||
for _, n := range names {
|
||||
ctx, cancel := context.WithTimeout(r.Context(), 4*time.Second)
|
||||
addrs, err := net.DefaultResolver.LookupHost(ctx, n)
|
||||
cancel()
|
||||
if err != nil || len(addrs) == 0 {
|
||||
setupFlash(w, r, "Имя «"+n+"» не найдено в DNS. Попросите администратора сети добавить на DNS-сервере (контроллере домена) запись A: "+
|
||||
n+" → "+strings.Join(serverIPs(), " или ")+" — и нажмите «Сохранить» ещё раз.")
|
||||
return
|
||||
}
|
||||
ok := false
|
||||
for _, a := range addrs {
|
||||
ok = ok || mine[a]
|
||||
}
|
||||
if !ok && len(mine) > 0 {
|
||||
setupFlash(w, r, "Имя «"+n+"» в DNS указывает на "+strings.Join(addrs, ", ")+", а у сервера bj адрес "+strings.Join(serverIPs(), ", ")+
|
||||
". Исправьте запись A на DNS-сервере и нажмите «Сохранить» ещё раз.")
|
||||
return
|
||||
}
|
||||
resolved = append(resolved, n+" → "+strings.Join(addrs, ", "))
|
||||
}
|
||||
h := rc.Snapshot().HTTPS
|
||||
h.Hostnames = names
|
||||
if err := rc.UpdateHTTPS(h); err != nil {
|
||||
setupFlash(w, r, "Имена сервера: "+err.Error())
|
||||
return
|
||||
}
|
||||
if h.Custom {
|
||||
setupFlash(w, r, "Имена сохранены. Сейчас используется загруженный сертификат организации — проверьте, что эти имена есть в нём.")
|
||||
return
|
||||
}
|
||||
if err := ensureSelfSigned(true); err != nil {
|
||||
setupFlash(w, r, "Имена сохранены, но сертификат не перевыпущен: "+err.Error())
|
||||
return
|
||||
}
|
||||
if len(names) == 0 {
|
||||
setupFlash(w, r, "Доменные имена убраны. Сертификат перевыпущен на имя хоста и IP.")
|
||||
return
|
||||
}
|
||||
setupFlash(w, r, "Готово: "+strings.Join(resolved, "; ")+" — имя есть в DNS и вписано в сертификат. Адрес bj: https://"+httpsHostPort(names[0], h.publicPort())+"/ (http:// перебросит на https:// сам). Сертификат самоподписанный — браузер один раз попросит подтвердить исключение; "+
|
||||
"без предупреждения — после загрузки сертификата организации («Сертификат организации» ниже).")
|
||||
msg, _ := saveHostnames(r.Context(), rc, r.FormValue("hostnames"))
|
||||
setupFlash(w, r, msg)
|
||||
})
|
||||
}
|
||||
|
||||
// saveHostnames — доменные имена сервера: проверка DNS (имя указывает на этот сервер), сохранение,
|
||||
// перевыпуск самоподписанного сертификата. Возвращает текст для пользователя и успех.
|
||||
func saveHostnames(ctx0 context.Context, rc *RuntimeConfig, raw string) (string, bool) {
|
||||
raw = strings.NewReplacer(",", " ", ";", " ", "\n", " ", "\r", " ").Replace(raw)
|
||||
var names []string
|
||||
for _, f := range strings.Fields(raw) {
|
||||
f = strings.ToLower(strings.TrimSpace(f))
|
||||
f = strings.TrimPrefix(f, "https://")
|
||||
f = strings.TrimPrefix(f, "http://")
|
||||
if i := strings.IndexByte(f, '/'); i >= 0 {
|
||||
f = f[:i]
|
||||
}
|
||||
if h, _, err := net.SplitHostPort(f); err == nil {
|
||||
f = h
|
||||
}
|
||||
if f == "" {
|
||||
continue
|
||||
}
|
||||
if !validHostname(f) {
|
||||
return "Доменное имя «" + f + "» задано неверно. Пример: m2m.corp.example.ru", false
|
||||
}
|
||||
names = append(names, f)
|
||||
}
|
||||
names = uniqStrings(names)
|
||||
// имя должно быть в DNS и указывать на этот сервер — иначе браузер всё равно не откроет bj по нему
|
||||
mine := map[string]bool{}
|
||||
for _, ip := range serverIPs() {
|
||||
mine[ip] = true
|
||||
}
|
||||
var resolved []string
|
||||
for _, n := range names {
|
||||
ctx, cancel := context.WithTimeout(ctx0, 4*time.Second)
|
||||
addrs, err := net.DefaultResolver.LookupHost(ctx, n)
|
||||
cancel()
|
||||
if err != nil || len(addrs) == 0 {
|
||||
return "Имя «" + n + "» не найдено в DNS. Попросите администратора сети добавить на DNS-сервере (контроллере домена) запись A: " +
|
||||
n + " → " + strings.Join(serverIPs(), " или ") + " — и нажмите «Сохранить» ещё раз.", false
|
||||
}
|
||||
ok := false
|
||||
for _, a := range addrs {
|
||||
ok = ok || mine[a]
|
||||
}
|
||||
if !ok && len(mine) > 0 {
|
||||
return "Имя «" + n + "» в DNS указывает на " + strings.Join(addrs, ", ") + ", а у сервера bj адрес " + strings.Join(serverIPs(), ", ") +
|
||||
". Исправьте запись A на DNS-сервере и нажмите «Сохранить» ещё раз.", false
|
||||
}
|
||||
resolved = append(resolved, n+" → "+strings.Join(addrs, ", "))
|
||||
}
|
||||
h := rc.Snapshot().HTTPS
|
||||
h.Hostnames = names
|
||||
if err := rc.UpdateHTTPS(h); err != nil {
|
||||
return "Имена сервера: " + err.Error(), false
|
||||
}
|
||||
if h.Custom {
|
||||
return "Имена сохранены. Сейчас используется загруженный сертификат организации — проверьте, что эти имена есть в нём.", true
|
||||
}
|
||||
if err := ensureSelfSigned(true); err != nil {
|
||||
return "Имена сохранены, но сертификат не перевыпущен: " + err.Error(), false
|
||||
}
|
||||
if len(names) == 0 {
|
||||
return "Доменные имена убраны. Сертификат перевыпущен на имя хоста и IP.", true
|
||||
}
|
||||
return "Готово: " + strings.Join(resolved, "; ") + " — имя есть в DNS и вписано в сертификат. Адрес bj: https://" + httpsHostPort(names[0], h.publicPort()) + "/ (http:// перебросит на https:// сам). Сертификат самоподписанный — браузер один раз попросит подтвердить исключение; " +
|
||||
"без предупреждения — после загрузки сертификата организации («Сертификат организации» ниже).", true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user