Dans mon script j'ai:
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}"
L'exécuter sur Windows dans Git Bash 3.1 donne:
Subject does not start with '/'.
Essayé d'échapper au sujet comme ça: -subj\"/ C = UK/ST = un endroit/L = Provo/O = Achme/CN = $ {FQDN} \"
Ça ne marche toujours pas. Des idées?
Ce problème est spécifique à MinGW/MSYS, qui est couramment utilisé dans le cadre du package Git pour Windows.
La solution consiste à passer l'argument -subj
avec le préfixe //
(doubles barres obliques), puis à utiliser \
(barres obliques inverses) pour séparer les paires clé/valeur. Comme ça:
"//O=Org\CN=Name"
Comme par magie, ceci sera passé à openssl
sous la forme attendue:
"/O=Org/CN=Name"
Donc, pour répondre à la question spécifique, vous devez modifier la ligne -subj
de votre script comme suit.
-subj "//C=GB\ST=someplace\L=Provo\O=Achme\CN=${FQDN}"
Cela devrait être tout ce dont vous avez besoin.
Pour ceux qui sont curieux de savoir exactement ce qui se passe ici, je peux expliquer ce mystère. La raison en est que MSYS suppose raisonnablement que les arguments contenant des barres obliques sont en réalité des chemins. Et lorsque ces arguments sont passés à un exécutable qui n'a pas été compilé spécifiquement pour MSYS (comme openssl
dans ce cas), il sera alors convertir les chemins POSIX en chemins Win32 . Les règles de cette conversion sont assez complexes car MSYS fait de son mieux pour couvrir les scénarios d'interopérabilité les plus courants. Cela explique également pourquoi l'utilisation de openssl
à partir d'une commande Windows Invite (cmd.exe
) fonctionne correctement, car aucune conversion magique n'est effectuée.
Vous pouvez tester la conversion comme ceci.
$ cmd //c echo "/CN=Name"
"C:/Program Files (x86)/Git/CN=Name"
Nous ne pouvons pas utiliser l'exécutable echo
fourni avec MSYS puisqu'il a été compilé pour MSYS; nous utiliserons plutôt le echo
intégré dans cmd
. Notez que puisque les commutateurs cmd
commencent par /
(commun aux commandes Windows), nous devons le gérer avec des doubles barres obliques. Comme nous pouvons le voir dans la sortie, l'argument a été étendu à un chemin Windows et nous comprenons pourquoi openssl
prétend en effet que Subject does not start with '/'.
.
Voyons encore quelques conversions.
$ cmd //c echo "//CN=Name"
/CN=Name
Les doubles barres obliques font croire à MSYS que l'argument est un commutateur de style Windows, ce qui entraîne la suppression d'un /
uniquement (pas de conversion de chemin). On pourrait penser qu'avec cela, nous pourrions simplement utiliser des barres obliques pour ajouter plus de paires clé/valeur. Essayons ça.
$ cmd //c echo "//O=Org/CN=Name"
//O=Org/CN=Name
Tout à coup, les doubles barres obliques au départ ne sont pas effacées. En effet, MSYS pense désormais que nous référons à un chemin UNC (par exemple, // serveur/chemin) après les barres doubles. Si ceci est passé à openssl
, la première clé/valeur sera omise en disant Subject Attribute /O has no known NID, skipped
.
Voici la règle pertinente du wiki de MinGW expliquant ce comportement:
- Un argument commençant par 2 ou plus/est considéré comme un commutateur de style Windows échappé et sera passé avec le préfixe/supprimé et tous les\remplacés par /.
- Sauf que s'il y a un/suivant le bloc de /, l'argument est considéré comme un chemin UNC et que le/ne est pas supprimé.
Dans cette règle, nous pouvons voir la méthode que nous pourrions utiliser pour créer l'argument que nous voulons. Puisque tous les \
qui suivent dans un argument commençant par //
seront convertis en plain /
. Essayons ça.
$ cmd //c echo "//O=Org\CN=Name"
/O=Org/CN=Name
Et comme on peut le constater, cela fonctionne.
J'espère que cela démystifie un peu la magie.
J'ai personnellement trouvé que cela était spécifique au binaire OpenSSL utilisé. Sur mon système utilisant msys2/mingw64, j'ai remarqué la présence de deux binaires OpenSSL différents, par exemple:
$ 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
Je crois que c'est l'utilisation de /mingw64/bin/openssl
qui nécessite l'utilisation d'un sujet qui commence par //
, mais je ne suis pas sûr que cela soit spécifique au package/build ou à la version d'OpenSSL. Pour être sûr, la version de chaque binaire est au dessous de:
$ 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
J'ai trouvé l'exemple suivant de code bash permettant de sélectionner le bon binaire basé sur la version OpenSSL lors de l'utilisation de msys/mingw pour travailler sur ma machine:
# 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
En plus de la résolution des problèmes liés à la transmission de la chaîne de sujet, j’ai également constaté que cette méthode permettait de résoudre les problèmes liés à la taille du nom distinctif (j’ai passé un openssl.cnf personnalisé avec une stratégie qui ne définissait pas de taille maximale pour aucun des champs et qui posait toujours des problèmes. en utilisant /mingw64/bin/openssl.exe
).