Chạy Openssl từ một tập lệnh bash trên windows - Chủ đề không bắt đầu bằng '/'


81

Trong kịch bản của tôi, tôi có:

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}"

Chạy điều này trên Windows trong Git Bash 3.1 cho:

Subject does not start with '/'.

Đã cố gắng thoát khỏi subj như vậy: -subj \ "/ C = UK / ST = someplace / L = Provo / O = Achme / CN = $ {FQDN} \"

Vẫn không hoạt động. Có ý kiến ​​gì không?


1
Câu hỏi đầu tiên tiêu chuẩn: tệp script của bạn có phần cuối dòng kiểu DOS / Windows (ký tự xuống dòng + dòng cấp) hay kiểu unix (chỉ dòng)? Thử in script bằng cat -vet /path/to/scriptvà xem các dòng kết thúc bằng '^ M $' (kiểu Windows) hay chỉ bằng '$' (kiểu unix).
Gordon Davisson,

1
Đây là một kịch bản bash? Chạy trong môi trường nào? Việc thêm set -vxvào đầu chương trình kịch bản đang được chạy cho dòng này là gì?
Etan Reisner,

@EtanReisner set -vxrất hữu ích, cảm ơn! Môi trường là Windows, Git bash 3.1. Với -vx , tôi nhận được + 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.comhiển thị chuỗi không được trích dẫn -subj. Nhưng tôi không thể tìm ra cách chuyển điều này thành một dạng trích dẫn từ kịch bản.
Iss42

@GordonDavisson cảm ơn! script có phần cuối dòng là '^ M $'
Iss42

1
Một đối số không được trích dẫn trong -vxđầu ra không có gì đáng ngạc nhiên hoặc là một vấn đề. Các dấu ngoặc kép dành cho việc phân tích cú pháp shell không phải bản thân việc thực thi lệnh. Đầu ra đó có vẻ chính xác với tôi. Kết thúc dòng DOS nói chung không phải là một ý tưởng hay nhưng dường như không gây ra bất kỳ vấn đề nào ở đây (trừ khi việc xóa chúng sẽ khắc phục được sự cố trong trường hợp đó tôi hơi bối rối bởi thông báo lỗi).
Etan Reisner,

Câu trả lời:


195

Sự cố này là riêng đối với MinGW / MSYS thường được sử dụng như một phần của gói Git dành cho Windows .

Giải pháp là chuyển -subjđối số với hàng đầu //(dấu gạch chéo kép về phía trước) và sau đó sử dụng \(dấu gạch chéo ngược) để phân tách các cặp khóa / giá trị. Như thế này:

"//O=Org\CN=Name"

Điều này sau đó sẽ được chuyển đến một cách kỳ diệu opensslở dạng mong đợi:

"/O=Org/CN=Name"

Vì vậy, để trả lời câu hỏi cụ thể, bạn nên thay đổi -subjdòng trong script của mình thành dòng sau.

-subj "//C=GB\ST=someplace\L=Provo\O=Achme\CN=${FQDN}"

Đó phải là tất cả những gì bạn cần.

Phép thuật này là gì?

Đối với những người tò mò về chính xác những gì đang diễn ra ở đây, tôi có thể giải thích bí ẩn này. Lý do là MSYS giả định một cách hợp lý rằng các đối số chứa dấu gạch chéo thực sự là đường dẫn. Và khi những đối số đó được chuyển đến một tệp thực thi chưa được biên dịch riêng cho MSYS (như openssltrong trường hợp này) thì nó sẽ chuyển đổi đường dẫn POSIX thành đường dẫn Win32 . Các quy tắc cho việc chuyển đổi này khá phức tạp vì MSYS cố gắng hết sức để giải quyết hầu hết các tình huống phổ biến về khả năng tương tác. Điều này cũng giải thích tại sao việc sử dụng openssltừ dấu nhắc lệnh windows ( cmd.exe) hoạt động tốt, vì không có chuyển đổi ma thuật nào được thực hiện.

Bạn có thể thử nghiệm chuyển đổi như thế này.

$ cmd //c echo "/CN=Name"
"C:/Program Files (x86)/Git/CN=Name"

Chúng tôi không thể sử dụng echotệp thực thi đi kèm với MSYS vì nó được biên dịch cho MSYS, thay vào đó chúng tôi sẽ sử dụng echonội trang trong cmd. Lưu ý rằng vì cmdcông tắc bắt đầu bằng /(phổ biến đối với các lệnh windows) nên chúng ta cần xử lý điều đó bằng dấu gạch chéo kép. Như chúng ta có thể thấy trong đầu ra, đối số đã được mở rộng thành đường dẫn cửa sổ và nó trở nên rõ ràng tại sao opensslthực sự khẳng định điều đó Subject does not start with '/'..

Hãy xem thêm một số chuyển đổi.

$ cmd //c echo "//CN=Name"
/CN=Name

Dấu gạch chéo kép khiến MSYS tin rằng đối số là một chuyển đổi kiểu cửa sổ dẫn đến việc loại bỏ một /chỉ (không có chuyển đổi đường dẫn). Bạn sẽ nghĩ rằng với điều này, chúng tôi chỉ có thể sử dụng dấu gạch chéo để thêm nhiều cặp khóa / giá trị hơn. Hãy thử điều đó.

$ cmd //c echo "//O=Org/CN=Name"
//O=Org/CN=Name

Đột nhiên, dấu gạch chéo đôi khi bắt đầu không được gỡ bỏ. Điều này là do bây giờ, với dấu gạch chéo sau dấu gạch chéo kép ban đầu, MSYS nghĩ rằng chúng ta đang tham chiếu đến một đường dẫn UNC (ví dụ: // server / path). Nếu điều này được chuyển cho opensslnó sẽ bỏ qua câu nói khóa / giá trị đầu tiên Subject Attribute /O has no known NID, skipped.

Đây là quy tắc liên quan từ wiki MinGW giải thích hành vi này:

  • Một đối số bắt đầu bằng 2 trở lên / được coi là một chuyển đổi kiểu Windows đã thoát và sẽ được chuyển với phần đầu / loại bỏ và tất cả \ được thay đổi thành /.
    • Ngoại trừ việc nếu có một / theo sau khối đứng đầu của /, thì đối số được coi là một đường dẫn UNC và khối đứng đầu / không bị loại bỏ.

Trong quy tắc này, chúng ta có thể thấy phương pháp chúng ta có thể sử dụng để tạo đối số mà chúng ta muốn. Vì tất cả những \gì theo sau trong một đối số bắt đầu bằng //sẽ được chuyển thành đơn giản /. Hãy thử điều đó.

$ cmd //c echo "//O=Org\CN=Name"
/O=Org/CN=Name

Và như chúng ta có thể thấy nó hoạt động.

Hy vọng điều này làm sáng tỏ điều kỳ diệu một chút.


1
Lời giải thích tuyệt vời.
trebor

4
Điều gì sẽ xảy ra nếu tôi sử dụng cùng một bash-script để tạo khóa trong môi trường linux? Làm thế nào sẽ được giải thích rằng dấu gạch chéo kép đứng đầu và dấu gạch chéo ngược ở giữa dòng?
Tomilov Anatoliy

3
@Orient Linux cần các dấu gạch chéo theo hướng khác, vì vậy bạn sẽ cần phát hiện loại hệ thống mà nó đang chạy - đây là câu trả lời sử dụng một casecâu lệnh và uname -sđể phát hiện môi trường, sau đó bạn có thể sử dụng với một ifđể sử dụng dấu gạch chéo - stackoverflow.com/questions/3466166/…
Tim Lewis

Hoàn toàn tuyệt vời. Tôi đã gặp vấn đề tương tự và hoàn toàn quên mất việc chuyển đổi đường dẫn từ POSIX sang Win32. Tôi nghĩ rằng tôi đã trích dẫn nó sai.
davewasthere

0

Cá nhân tôi thấy điều này dành riêng cho nhị phân OpenSSL đang được sử dụng. Trên hệ thống của tôi sử dụng msys2 / mingw64, tôi đã nhận thấy rằng có hai mã nhị phân OpenSSL khác nhau, ví dụ:

$ 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

Tôi tin rằng việc sử dụng /mingw64/bin/opensslyêu cầu phải sử dụng chủ đề bắt đầu bằng //, tuy nhiên tôi không chắc liệu điều này dành riêng cho gói / bản dựng hay phiên bản OpenSSL, vì vậy để chắc chắn, phiên bản của mỗi tệp nhị phân là bên dưới:

$ 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

Tôi đã tìm thấy ví dụ sau về mã bash để chọn mã nhị phân chính xác dựa trên phiên bản OpenSSL khi sử dụng msys / mingw để làm việc trên máy của tôi:

# 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

Ngoài việc khắc phục sự cố với việc chuyển chuỗi chủ đề, tôi cũng tìm thấy điều này để giải quyết các vấn đề với kích thước của DN (Tôi đã thông qua openssl.cnf tùy chỉnh với chính sách không đặt max_size cho bất kỳ trường nào và vẫn có vấn đề khi sử dụng /mingw64/bin/openssl.exe).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.