Можно ли избежать ввода пароля хранилища ключей в командной строке с JSSE? - PullRequest
7 голосов
/ 09 марта 2011

Мы используем Maven 2 и у нас есть менеджер репозитория maven, защищенный аутентификацией клиента SSL.Чтобы Maven мог получить доступ к хранилищу, в Java должны быть переданы следующие системные свойства:

javax.net.ssl.trustStore = trust.jks
javax.net.ssl.trustStorePassword = <trustPass>
javax.net.ssl.keyStore = keystore.p12
javax.net.ssl.keyStoreType = pkcs12
javax.net.ssl.keyStorePassword = <keyStorePass>

См. мини-руководство для получения более подробной информации.

Чтобы установить эти системные свойства в Maven, я должен использовать переменную среды MAVEN_OPTS (или передать их непосредственно в командной строке).В любом случае, когда Maven действительно выполняется, все эти свойства становятся видимыми для других пользователей системы (через ps), включая мой пароль хранилища ключей.

Есть ли способ установить эти свойства так, чтобы пароль нене разоблачить в командной строке?

Ответы [ 4 ]

4 голосов
/ 18 мая 2012

OSX

Решение, которое я придумал для OSX, следующее .mavenrc. Он использует скрипт Python для доступа к паролю в цепочке для ключей, чтобы открыть сертификат клиента, а затем генерирует случайную фразу-пароль и временный сертификат с этим случайным паролем.

Поместите это в ~/.mavenrc и добавьте свой сертификат клиента в цепочку ключей OSX. Убедитесь, что в настройках MAVEN_CLIENT_CERT указано местоположение сертификата клиента.

~ / .mavenrc

export MAVEN_CLIENT_CERT=<PATH.TO.CLIENT.CERTIFICATE>

# Retrieve secret from keychain
export SECRET=$(python <<END
from subprocess import Popen, PIPE
import re, sys, os

passlabel = os.environ.get("MAVEN_CLIENT_CERT", None)

p = Popen(['security', 'find-generic-password', '-l',passlabel,'-g'], stdout=PIPE, stderr=PIPE, stdin=PIPE)

sys.stdout.write(re.compile('password:\\s"(.*)"').match(p.stderr.read()).group(1))
sys.exit(0)
END)

TMPDIR=/tmp
TMPTMPL=mvn-$(id -u)-XXXXXXXXXX
PASSPHRASE=$(openssl rand -base64 32)
export PASSPHRASE TMPDIR

pemfile=$(mktemp $TMPDIR/$TMPTMPL)
openssl pkcs12 -in $MAVEN_CLIENT_CERT -passin env:SECRET -out $pemfile -passout env:PASSPHRASE
p12file=$(mktemp $TMPDIR/$TMPTMPL)
openssl pkcs12 -export -in $pemfile -out $p12file -passin env:PASSPHRASE -passout env:PASSPHRASE

sh -c "while kill -0 $$ 2>/dev/null; do sleep 1; done; rm -f $pemfile; rm -f $p12file;" &

MAVEN_OPTS="$MAVEN_OPTS -Djavax.net.ssl.keyStore=$p12file -Djavax.net.ssl.keyStoreType=pkcs12 -Djavax.net.ssl.keyStorePassword=$PASSPHRASE"

Linux

В Linux следующий .mavenrc будет работать с набором ключей gnome (убедитесь, что добавили сертификатный пароль в ваш набор ключей входа в систему и установите переменную id KEYRING_ID):

~ / .mavenrc

MAVEN_CLIENT_CERT=<PATH.TO.CLIENT.CERTIFICATE>

export KEYRING_NAME="login"
export KEYRING_ID=<KEYRING.ID>

# Try to get secret from the gnome keyring 
export SECRET=$(python <<END
import sys, os
# Test for gtk
try:
  import gtk #ensure that the application name is correctly set
  import gnomekeyring as gk
except ImportError:
  gtk = None
if gtk:
  id = os.environ.get("KEYRING_ID", None)
  name = os.environ.get("KEYRING_NAME", None)
  try:
    if id:
      info = gk.item_get_info_sync(name, int(id))
      attr = gk.item_get_attributes_sync(name, int(id))
      sys.stdout.write(str(info.get_secret()))
    else:
      params = {}
      types = {'secret': gk.ITEM_GENERIC_SECRET, 'network': gk.ITEM_NETWORK_PASSWORD, 'note': gk.ITEM_NOTE}
      eparams = os.environ.get("KEYRING_PARAMS", None)
      etype = os.environ.get("KEYRING_ITEMTYPE", None)
      if eparams and etype:
        list = eparams.split(',')
        for i in list:
          if i:
            k, v = i.split('=', 1)
            if v.isdigit():
              params[k] = int(v)
            else:
              params[k] = v
        matches = gk.find_items_sync(types[etype], params)
        # Write 1st out and break out of loop. 
        # TODO: Handle more then one secret.
        for match in matches:
          sys.stdout.write(str(match.secret))
          break
    sys.exit(0)
  except gk.Error:
    pass
sys.exit(1)
END
)

TMPDIR=/dev/shm
TMPTMPL=mvn-$(id -u)-XXXXXXXXXX
PASSPHRASE=$(openssl rand -base64 32)
export PASSPHRASE TMPDIR

pemfile=$(mktemp $TMPDIR/$TMPTMPL)
openssl pkcs12 -in $MAVEN_CLIENT_CERT -passin env:SECRET -out $pemfile -passout env:PASSPHRASE
p12file=$(mktemp $TMPDIR/$TMPTMPL)
openssl pkcs12 -export -in $pemfile -out $p12file -passin env:PASSPHRASE -passout env:PASSPHRASE

sh -c "while kill -0 $$ 2>/dev/null; do sleep 1; done; rm -f $pemfile; rm -f $p12file;" &

MAVEN_OPTS="$MAVEN_OPTS -Djavax.net.ssl.keyStore=$p12file -Djavax.net.ssl.keyStoreType=pkcs12 -Djavax.net.ssl.keyStorePassword=$PASSPHRASE"
3 голосов
/ 18 мая 2012

В OSX вы можете использовать свою цепочку для ключей в качестве хранилища ключей (насколько я знаю, все еще есть ошибка, поэтому она работает только при наличии только одной «идентичности», то есть одной комбинации сертификата + секретного ключа ).

Используйте это, используйте -Djavax.net.ssl.keyStore=NONE, -Djavax.net.ssl.keyStoreType=KeychainStore и -Djavax.net.ssl.keyStorePassword=-.

Затем цепочка для ключей предложит вам одобрить использование закрытого ключа, когда это потребуется.

2 голосов
/ 08 октября 2011

Вы можете определить эти свойства в вашем файле настроек Maven.Они будут доступны так же, как и при вводе их в командной строке.Вот пример для вашего файла настроек Maven:

<profiles>
    <profile>
        <id>repo-ssl</id>
        <properties>
            <javax.net.ssl.trustStore>trust.jks</javax.net.ssl.trustStore>
            <javax.net.ssl.trustStorePassword>SET_TRUSTSTORE_PASSWORD</javax.net.ssl.trustStorePassword>
            <javax.net.ssl.keyStore>keystore.p12</javax.net.ssl.keyStore>
            <javax.net.ssl.keyStoreType>pkcs12</javax.net.ssl.keyStoreType>
            <javax.net.ssl.keyStorePassword>SET_KEYSTORE_PASSWORD</javax.net.ssl.keyStorePassword>
        </properties>
    </profile>
</profiles>

<activeProfiles>
    <activeProfile>repo-ssl</activeProfile>
</activeProfiles>

Хотя я не сделал то же самое, что и вы, я использовал эту же технику при работе с секретами.

0 голосов
/ 08 октября 2011

Да, вы можете либо использовать System.setProperty() в своем коде до получения исходного SSLContext, либо вы можете испытать муки и боль от создания собственного KeyManager и т. Д. И т. Д., Как описано с примерами в Справочном руководстве JSEE.

...