Windows의 bash 스크립트에서 Openssl 실행-제목이 '/'로 시작하지 않음


83

내 스크립트에는 다음이 있습니다.

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

Windows에서 Git Bash 3.1을 실행하면 다음이 제공됩니다.

Subject does not start with '/'.

다음과 같이 subj를 이스케이프했습니다. -subj \ "/ C = UK / ST = someplace / L = Provo / O = Achme / CN = $ {FQDN} \"

여전히 작동하지 않습니다. 어떤 아이디어?


1
표준 첫 번째 질문 : 스크립트 파일에 DOS / Windows 스타일 줄 끝 (캐리지 리턴 + 줄 바꿈)이 있습니까, 아니면 유닉스 스타일 (줄 바꿈 만)이 있습니까? 를 사용하여 스크립트를 인쇄하고 cat -vet /path/to/script행이 '^ M $'(Windows 스타일) 또는 '$'(unix 스타일)로 끝나는 지 확인하십시오.
Gordon Davisson

1
이것은 bash 스크립트입니까? 어떤 환경에서 실행합니까? set -vx이 줄에 대해 스크립트 상단에 추가 가 실행되는 것은 무엇입니까?
Etan Reisner 2015

@EtanReisner set -vx는 유용합니다 감사합니다! 환경은 Windows, Git bash 3.1입니다. 함께 -vx , 내가 얻을 수 + 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있는 표시되지 않은 인용 -subj문자열입니다. 그러나 나는 이것을 스크립트에서 인용 된 형태로 얻는 방법을 알 수 없습니다.
iss42 2015-07-20

@GordonDavisson 감사합니다! 스크립트에 '^ M $'줄 끝이 있습니다
iss42

1
-vx출력 에서 인용되지 않은 인수는 놀랍거나 문제가 아닙니다. 따옴표는 명령 실행 자체가 아닌 쉘 구문 분석을위한 것입니다. 그 출력은 나에게 맞는 것 같습니다. DOS 줄 끝은 일반적으로 좋은 생각은 아니지만 여기서 문제를 일으키는 것으로 보이지는 않습니다 (이를 제거하면 문제가 해결되지 않는 한 오류 메시지로 인해 혼란스러워집니다).
Etan Reisner 2015

답변:


197

이 문제는 일반적으로 일부로 사용되는 MinGW / MSYS 에만 해당됩니다 . Windows 용 Git 패키지의 .

해결책은 -subj인수를 선행 //(이중 슬래시) 으로 전달한 다음 \(백 슬래시)를 사용 하여 키 / 값 쌍을 구분하는 것입니다. 이렇게 :

"//O=Org\CN=Name"

그러면 openssl예상 된 형식 으로 마술처럼 전달됩니다 .

"/O=Org/CN=Name"

따라서 특정 질문에 답하려면 -subj스크립트 의 줄을 다음과 같이 변경해야합니다 .

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

그게 필요한 전부입니다.

이 마법은 무엇입니까?

여기서 무슨 일이 일어나고 있는지 정확히 궁금한 사람들을 위해이 미스터리를 설명 할 수 있습니다. 그 이유는 MSYS가 슬래시를 포함하는 인수가 실제로 경로라고 합리적으로 가정하기 때문입니다. 그리고 이러한 인수가 MSYS를 위해 특별히 컴파일되지 않은 실행 파일에 전달되면 ( openssl이 경우 처럼 ) POSIX 경로를 Win32 경로로 변환합니다 . MSYS는 상호 운용성에 대한 가장 일반적인 시나리오를 처리하기 위해 최선을 다하기 때문에이 변환에 대한 규칙은 매우 복잡합니다. 이것은 또한 opensslWindows 명령 프롬프트 (cmd.exe 마법적인 변환이 수행되지 않기 때문에 ) 잘 작동 .

이와 같이 변환을 테스트 할 수 있습니다.

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

우리는 사용할 수 없습니다 echo대신에 우리가 사용하는 것, 그것이 MSYS 컴파일 된 이후 MSYS와 함께 제공 실행 echo에 내장을 cmd. cmd스위치가 /(Windows 명령의 경우 공통)으로 시작 하므로 이중 슬래시로 처리해야합니다. 출력에서 볼 수 있듯이 인수는 Windows 경로로 확장되었으며 openssl실제로 Subject does not start with '/'..

더 많은 전환을 보겠습니다.

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

이중 슬래시는 MSYS가 인수가 Windows 스타일 스위치라고 믿게하여 /경로 변환없이 만 제거하는 결과를 가져옵니다 . 이를 통해 더 많은 키 / 값 쌍을 추가하기 위해 슬래시를 사용할 수 있다고 생각할 것입니다. 시도해 봅시다.

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

갑자기 시작 부분의 이중 슬래시가 제거되지 않습니다. 이것은 초기 이중 슬래시 뒤에 슬래시가있는 MSYS가 UNC 경로 (예 : // server / path)를 참조하고 있다고 생각하기 때문입니다. 이것이 전달되면 openssl라고 말하는 첫 번째 키 / 값을 건너 뜁니다 Subject Attribute /O has no known NID, skipped.

다음은 이 동작을 설명 하는 MinGW 위키 의 관련 규칙입니다 .

  • 2 개 이상의 /로 시작하는 인수는 이스케이프 된 Windows 스타일 스위치로 간주되며 선행 / 제거되고 모든 \가 /로 변경된 상태로 전달됩니다.
    • /의 선행 블록 뒤에 /가있는 경우를 제외하고는 인수는 UNC 경로로 간주되고 선행 /는 제거되지 않습니다.

이 규칙에서 원하는 인수를 생성하는 데 사용할 수있는 방법을 볼 수 있습니다. 로 \시작하는 인수 뒤에 오는 모든 것은 //plain으로 변환되기 때문 /입니다. 그것을 시도해 봅시다.

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

그리고 우리가 볼 수 있듯이 작동합니다.

이것이 마법을 조금 이해하기를 바랍니다.


1
훌륭한 설명.
trebor nov.

4
bashLinux 환경에서 동일한 스크립트를 사용하여 키를 생성 하면 어떻게됩니까? 행 중간에 선행 이중 슬래시와 백 슬래시를 어떻게 해석 할 수 있습니까?
Tomilov Anatoliy

3
@Orient Linux는 다른 방향으로 슬래시가 필요하므로 실행중인 시스템 유형을 감지해야합니다. 여기에는 case명령문 을 사용 uname -s하고 환경을 감지 하는 답변이 if있습니다. 슬래시 - stackoverflow.com/questions/3466166/...
팀 루이스

엄청나 다. 나는 같은 문제에 걸렸고 POSIX에서 Win32 로의 경로 변환에 대해 완전히 잊었습니다. 내가 잘못 인용하고 있다고 생각했습니다.
davewasthere

0

개인적으로 이것이 사용중인 OpenSSL 바이너리에만 해당된다는 것을 알았습니다. msys2 / mingw64를 사용하는 시스템에서 두 개의 다른 OpenSSL 바이너리가 있음을 발견했습니다. 예를 들면 다음과 같습니다.

$ 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

으로 /mingw64/bin/openssl시작하는 주제를 사용해야한다고 생각 //하지만 이것이 패키지 / 빌드 또는 OpenSSL 버전에 특정한 것인지 확실하지 않으므로 각 바이너리의 버전은 다음과 같습니다.

$ 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

msys / mingw를 사용하여 내 컴퓨터에서 작업 할 때 OpenSSL 버전을 기반으로 올바른 바이너리를 선택하는 bash 코드의 다음 예제를 찾았습니다.

# 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

제목 문자열 전달 문제를 수정하는 것 외에도 DN 크기 문제를 해결하기 위해이를 발견했습니다 (필드에 대해 max_size를 설정하지 않고 여전히 문제가있는 정책으로 사용자 정의 openssl.cnf를 전달했습니다. 사용할 때 /mingw64/bin/openssl.exe).

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.