W swoim skrypcie mam:
openssl req \
-x509 \
-new \
-nodes \
-key certs/ca/my-root-ca.key.pem \
-days 3652 \
-out certs/ca/my-root-ca.crt.pem \
-subj "/C=GB/ST=someplace/L=Provo/O=Achme/CN=${FQDN}"
Uruchomienie tego w systemie Windows w Git Bash 3.1 daje:
Subject does not start with '/'.
Próbowano uciekać przed subj w następujący sposób: -subj \ "/ C = UK / ST = gdzieś / L = Provo / O = Achme / CN = $ {FQDN} \"
Nadal nie działa. Jakieś pomysły?
cat -vet /path/to/script
i zobacz, czy wiersze kończą się na „^ M $” (w stylu Windows), czy po prostu na „$” (w stylu unix).set -vx
na początku pokazu skryptu jest uruchamiane dla tej linii?set -vx
jest przydatny dzięki! Środowisko to Windows, Git bash 3.1. Z -vx , otrzymuję,+ openssl req -x509 -new -nodes -key certs/ca/my-root-ca.key.pem -days 3652 -out certs/ca/my-root-ca.crt.pem -subj /C=GB/ST=someplace/L=Provo/O=Achme/CN=domain.com
który pokazuje-subj
ciąg znaków bez cudzysłowów . Ale nie mogę wymyślić, jak umieścić to w cytowanej formie ze scenariusza.-vx
wyniku nie jest zaskakujący ani nie stanowi problemu. Cudzysłowy dotyczą analizy powłoki, a nie samego wykonania polecenia. Wydaje mi się, że ten wynik jest poprawny. Zakończenia linii DOS generalnie nie są dobrym pomysłem, ale wydaje się, że nie spowodowały tutaj żadnych problemów (chyba że ich usunięcie rozwiązuje problem, w którym to przypadku jestem trochę zdezorientowany komunikatem o błędzie).Odpowiedzi:
Ten problem jest specyficzny dla MinGW / MSYS, który jest powszechnie używany jako część pakietu Git for Windows .
Rozwiązaniem jest przekazanie
-subj
argumentu z początkiem//
(podwójne ukośniki w przód), a następnie użycie\
(ukośnika odwrotnego) do oddzielenia par klucz / wartość. Lubię to:"//O=Org\CN=Name"
Zostanie to następnie magicznie przekazane
openssl
w oczekiwanej formie:"/O=Org/CN=Name"
Aby odpowiedzieć na konkretne pytanie, należy zmienić
-subj
wiersz w skrypcie na następujący.-subj "//C=GB\ST=someplace\L=Provo\O=Achme\CN=${FQDN}"
To powinno wystarczyć.
Co to za magia?
Dla ciekawych tego, co się tutaj dzieje, mogę wyjaśnić tę tajemnicę. Powodem jest to, że MSYS rozsądnie zakłada, że argumenty zawierające ukośniki są w rzeczywistości ścieżkami. A kiedy te argumenty są przekazywane do pliku wykonywalnego, który nie został skompilowany specjalnie dla MSYS (tak jak
openssl
w tym przypadku), wówczas konwertuje on ścieżki POSIX na ścieżki Win32 . Zasady tej konwersji są dość złożone, ponieważ MSYS stara się jak najlepiej uwzględniać większość typowych scenariuszy współdziałania. To wyjaśnia również, dlaczego używanieopenssl
z wiersza poleceń systemu Windows (cmd.exe
) działa dobrze, ponieważ nie są wykonywane żadne magiczne konwersje.Możesz przetestować konwersję w ten sposób.
$ cmd //c echo "/CN=Name" "C:/Program Files (x86)/Git/CN=Name"
Nie możemy użyć
echo
pliku wykonywalnego, który jest dostarczany z MSYS, ponieważ został skompilowany dla MSYS, zamiast tego użyjemyecho
wbudowanegocmd
. Zauważ, że ponieważcmd
przełączniki zaczynają się od/
(typowe dla poleceń systemu Windows), musimy obsługiwać to za pomocą podwójnych ukośników. Jak widać na wyjściu, argument został rozszerzony do ścieżki systemu Windows i staje się jasne, dlaczegoopenssl
rzeczywiście tak twierdziSubject does not start with '/'.
.Zobaczmy więcej konwersji.
$ cmd //c echo "//CN=Name" /CN=Name
Podwójne ukośniki sprawiają, że MSYS uważa, że argument jest przełącznikiem stylu systemu Windows, który powoduje usunięcie
/
tylko (bez konwersji ścieżki). Można by pomyśleć, że dzięki temu moglibyśmy po prostu użyć ukośników, aby dodać więcej par klucz / wartość. Spróbujmy tego.$ cmd //c echo "//O=Org/CN=Name" //O=Org/CN=Name
Nagle podwójne cięcia na początku nie są usuwane. Dzieje się tak, ponieważ teraz, z ukośnikiem po początkowych podwójnych ukośnikach, MSYS uważa, że odwołujemy się do ścieżki UNC (np. // serwer / ścieżka). Gdyby to zostało przekazane do
openssl
tego, pomijałoby pierwszy klucz / wartość mówiącąSubject Attribute /O has no known NID, skipped
.Oto odpowiednia reguła z wiki MinGW wyjaśniająca to zachowanie:
W tej regule widzimy metodę, której moglibyśmy użyć do stworzenia żądanego argumentu. Ponieważ wszystko,
\
co następuje w argumencie zaczynającym się od,//
zostanie przekonwertowane na zwykły/
. Wypróbujmy to.$ cmd //c echo "//O=Org\CN=Name" /O=Org/CN=Name
I jak widzimy, to działa.
Mam nadzieję, że to trochę demistyfikuje magię.
źródło
bash
użyję tego samego skryptu do generowania kluczy w środowisku linux? Jak można by zinterpretować, że wiodące podwójne ukośniki i odwrotne ukośniki na środku linii?case
instrukcji iuname -s
do wykrywania środowiska, którego możesz następnie użyć wif
celu użycia odpowiedniego slashy - stackoverflow.com/questions/3466166/…Osobiście uważam, że jest to specyficzne dla używanego pliku binarnego OpenSSL. W moim systemie używającym msys2 / mingw64 zauważyłem, że obecne są dwa różne pliki binarne OpenSSL, na przykład:
$ whereis openssl; echo; which openssl openssl: /usr/bin/openssl.exe /usr/lib/openssl /mingw64/bin/openssl.exe /usr/share/man/man1/openssl.1ssl.gz /mingw64/bin/openssl
Uważam, że użycie
/mingw64/bin/openssl
tego wymaga użycia tematu, który zaczyna się od//
, jednak nie jestem pewien, czy jest to specyficzne dla pakietu / kompilacji lub wersji OpenSSL, więc dla pewności wersja każdego pliku binarnego jest poniżej:$ while read -r _openSslBin; do printf "${_openSslBin}: "; ${_openSslBin} version; done < <(whereis openssl | egrep -o '[^ ]+?\.exe ') /usr/bin/openssl.exe: OpenSSL 1.0.2p 14 Aug 2018 /mingw64/bin/openssl.exe: OpenSSL 1.1.1 11 Sep 2018
Znalazłem następujący przykład kodu bash, aby wybrać poprawny plik binarny na podstawie wersji OpenSSL podczas używania msys / mingw do pracy na moim komputerze:
# determine openssl binary to use based on OS # ------------------------------------------- _os="$(uname -s | awk 'BEGIN{FS="_"} {print $1}' | egrep -o '[A-Za-z]+')" if [ "${_os,,}" = "mingw" ] || [ "${_os,,}" == "msys" ]; then while read -r _currentOpenSslBin; do if [[ "$(${_currentOpenSslBin} version | awk '{print $2}')" =~ ^(1\.0\.[0-9].*|0\.\9\.8.*)$ ]]; then _openSslBin="${_currentOpenSslBin}" fi done < <(whereis openssl | egrep -o '\/[^ ]+?\.exe ' | egrep -v 'mingw') if [ -n "${_openSslBin}" ]; then printf "OpenSSL Binary: ${_openSslBin} (v. $(${_openSslBin} version | awk '{print $2}'))\n" else printf "Unable to find compatible version of OpenSSL for use with '${_os}' OS, now exiting...\n" exit 1 fi else _openSslBin="openssl" fi # display selected openssl binary and it's version # ------------------------------------------------ printf "${_openSslBin}: "; ${_openSslBin} version
Oprócz naprawienia problemów z przekazywaniem ciągu tematu znalazłem również to, aby rozwiązać problemy z rozmiarem nazwy wyróżniającej (przekazałem niestandardowy plik openssl.cnf z polityką, która nie ustawiała max_size dla żadnego z pól i która nadal miała problemy podczas używania
/mingw64/bin/openssl.exe
).źródło