Fornecimento de senha para MySQL envolveu-up
-
03-07-2019 - |
Pergunta
Saudações.
Eu escrevi um script python pouco que chama MySQL em um subprocesso. [Sim, eu sei que a abordagem correta é usar MySQLdb, mas compilá-lo sob OS X Leopard é uma dor, e provavelmente mais doloroso se eu queria usar o script em computadores de diferentes arquiteturas.] As obras técnica subprocess, desde que I fornecer a senha no comando que inicia o processo; no entanto, isso significa que outros usuários na máquina podia ver a senha.
O código original que eu escrevi pode ser visto aqui .
Esta variante abaixo é muito semelhante, embora eu vou omitir a rotina de teste para mantê-lo mais curto:
#!/usr/bin/env python
from subprocess import Popen, PIPE
# Set the command you need to connect to your database
mysql_cmd_line = "/Applications/MAMP/Library/bin/mysql -u root -p"
mysql_password = "root"
def RunSqlCommand(sql_statement, database=None):
"""Pass in the SQL statement that you would like executed.
Optionally, specify a database to operate on. Returns the result."""
command_list = mysql_cmd_line.split()
if database:
command_list.append(database)
# Run mysql in a subprocess
process = Popen(command_list, stdin=PIPE, stdout=PIPE,
stderr=PIPE, close_fds=True)
#print "Asking for output"
#needs_pw = process.stdout.readline()
#print "Got: " + needs_pw
# pass it in the password
process.stdin.write(mysql_password + "\n")
# pass it our commands, and get the results
#(stdout, stderr) = process.communicate( mysql_password + "\n" + sql_statement)
(stdout, stderr) = process.communicate( sql_statement )
return stdout
Estou desconfiado de que a solicitação de senha MySQL não é realmente em stdout (ou stderr), embora eu não sei como isso pode ser ou se isso significa que eu poderia prendê-lo.
Eu tentei ler a saída do primeiro, antes de fornecer uma senha, mas não funcionou. Eu também tentei passar a senha
Mais uma vez, se eu fornecer a senha na linha de comando (e, portanto, não têm nenhum código entre o "Popen" e "comunicar" funções) meus trabalhos de função embrulhadas.
Dois novos pensamentos, meses laster:
-
Usando pexpect me deixaria fornecer uma senha. Ele simula um tty e recebe toda a saída, mesmo que ignora stdout e stderr.
-
Há um projeto chamado MySQL Connector / Python , em alfa precoce, que permitirá fornecer uma biblioteca pura python para acessar MySQL, sem a necessidade de compilar qualquer código C.
Solução
Você poderia simplesmente criar um arquivo my.cnf e apontam para que no comando mysql. Obviamente você vai querer proteger esse arquivo com permissões / acls. Mas não deve ser realmente um mais / menos segura em seguida, ter a senha em seu script python, ou a configuração para o seu script python.
Assim que você faria algo assim
mysql_cmd_line = "/Applications/MAMP/Library/bin/mysql --defaults-file=credentials.cnf"
e sua configuração ficaria mais ou menos assim
[client]
host = localhost
user = root
password = password
socket = /var/run/mysqld/mysqld.sock
Outras dicas
O único método seguro é usar um arquivo MySQL CNF como um dos outros cartazes menciona. Você também pode passar uma variável MYSQL_PWD env, mas isso é inseguro também: http://dev.mysql.com/doc/refman/5.0/en/password-security.html
Como alternativa, você pode se comunicar com o banco de dados usando um arquivo socket Unix e com um pouco de ajustes você pode controlar permissões no nível do ID do usuário.
Mesmo melhor, você pode usar o livre BitNami pilha DjangoStack que tem Python e mysqldb pré-compilados para OS X (E Windows e Linux) http://bitnami.org/stacks
Este pode ser um / recurso SQL Server do Windows, mas você pode usar uma conexão confiável (ou seja, usar o seu login OS / senha para acessar o DB)? Pode haver um equivalente OS X para o MySQL.
Ou você pode só precisa configurar seu banco de dados para usar o login OS e senha para que você não precisa mantê-lo em seu código.
De qualquer forma, apenas uma idéia.
Tente isto:
process.stdin.write(mysql_password + "\n")
process.communicate()
(stdout, stderr) = process.communicate( sql_statement )
process.stdin.close()
return stdout
Chamada comunicar () para forçar o que você acabou de escrever para o buffer para enviar. Além disso, é bom para perto stdin quando você está feito.