# #java #python #go #google-cloud-platform #google-cloud-functions
#java #python #Вперед #google-облачная платформа #google-cloud-функции
Вопрос:
Я пытаюсь создать облачную функцию Google, которая автоматизирует процесс создания пароля Windows для моего экземпляра виртуальной машины. Я нашел эту ссылку:https://cloud.google.com/compute/docs/instances/windows/automate-pw-generation#python
К сожалению, я регулярно использую Javascript, поэтому мне нужна помощь с Java, Python или Go. В этом случае я решил использовать python, но это не имеет значения.
Мои настройки: Среда выполнения: Python 3.7 Точка входа: main
Код
import base64
import copy
import datetime
import json
import time
from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA
from Crypto.Util.number import long_to_bytes
from oauth2client.client import GoogleCredentials
from googleapiclient.discovery import build
def GetCompute():
credentials = GoogleCredentials.get_application_default()
compute = build('compute', 'v1', credentials=credentials)
return compute
def GetInstance(compute, instance, zone, project):
cmd = compute.instances().get(instance=instance, project=project, zone=zone)
return cmd.execute()
def GetKey():
key = RSA.generate(2048)
return key
def GetModulusExponentInBase64(key):
mod = long_to_bytes(key.n)
exp = long_to_bytes(key.e)
modulus = base64.b64encode(mod)
exponent = base64.b64encode(exp)
return modulus, exponent
def GetExpirationTimeString():
utc_now = datetime.datetime.utcnow()
expire_time = utc_now datetime.timedelta(minutes=5)
return expire_time.strftime('%Y-%m-%dT%H:%M:%SZ')
def GetJsonString(user, modulus, exponent, email):
expire = GetExpirationTimeString()
data = {'userName': user,
'modulus': modulus,
'exponent': exponent,
'email': email,
'expireOn': expire}
return json.dumps(data)
def UpdateWindowsKeys(old_metadata, metadata_entry):
new_metadata = copy.deepcopy(old_metadata)
new_metadata['items'] = [{
'key': "windows-keys",
'value': metadata_entry
}]
return new_metadata
def UpdateInstanceMetadata(compute, instance, zone, project, new_metadata):
cmd = compute.instances().setMetadata(instance=instance, project=project, zone=zone, body=new_metadata)
return cmd.execute()
def GetSerialPortFourOutput(compute, instance, zone, project):
port = 4
cmd = compute.instances().getSerialPortOutput(instance=instance, project=project, zone=zone, port=port)
output = cmd.execute()
return output['contents']
def GetEncryptedPasswordFromSerialPort(serial_port_output, modulus):
output = serial_port_output.split('n')
for line in reversed(output):
try:
entry = json.loads(line)
if modulus == entry['modulus']:
return entry['encryptedPassword']
except ValueError:
pass
def DecryptPassword(encrypted_password, key):
decoded_password = base64.b64decode(encrypted_password)
cipher = PKCS1_OAEP.new(key)
password = cipher.decrypt(decoded_password)
return password
def main(request):
instance = 'my-instance'
zone = 'my-zone'
project = 'my-project'
user = 'my-user'
email = 'my-email'
compute = GetCompute()
key = GetKey()
modulus, exponent = GetModulusExponentInBase64(key)
instance_ref = GetInstance(compute, instance, zone, project)
old_metadata = instance_ref['metadata']
metadata_entry = GetJsonString(user, modulus, exponent, email)
new_metadata = UpdateWindowsKeys(old_metadata, metadata_entry)
result = UpdateInstanceMetadata(compute, instance, zone, project, new_metadata)
time.sleep(30)
serial_port_output = GetSerialPortFourOutput(compute, instance, zone, project)
enc_password = GetEncryptedPasswordFromSerialPort(serial_port_output, modulus)
password = DecryptPassword(enc_password, key)
print(f'Username: {user}')
print(f'Password: {password}')
ip = instance_ref['networkInterfaces'][0]['accessConfigs'][0]['natIP']
print(f'IP Address: {ip}')
Как вы можете видеть, я добавил свои данные в основную функцию и мой requirements.txt выглядит так:
pycrypto==2.6.1
oauth2client==4.1.3
К сожалению, это не работает, и я получаю следующую ошибку:
Объект типа bytes не является сериализуемым в формате JSON.
Я надеюсь, что вы сможете мне здесь помочь. Спасибо.
========
Редактировать
Я добавил «.decode ()» к модулю и экспоненте, чтобы избежать предыдущей ошибки:
def GetJsonString(user, modulus, exponent, email):
expire = GetExpirationTimeString()
data = {'userName': user,
'modulus': modulus.decode(),
'exponent': exponent.decode(),
'email': email,
'expireOn': expire}
return json.dumps(data)
Но я все еще не могу сгенерировать пароль. Я получаю сообщение об ошибке «serial_port_output = GetSerialPortFourOutput (вычисление, экземпляр, зона, проект)»:
модуль декодирования ошибок: недопустимые данные base64 во входном байте 1
Ответ №1:
Ваша функция не работает, потому что вы используете оператор печати Python 2.x вместо функции python3 print().
Заменить
print 'Username: {0}'.format(user)
с помощью
print ('Username: {0}'.format(user))
Вы также можете использовать python 3.6 f-strings вместо format()
pring(f'Username: {user}')
Комментарии:
1. Спасибо за ваш ответ. Это верно. Спасибо. К сожалению, появляется другая ошибка: «Объект типа bytes не является сериализуемым в формате JSON». Проблема должна быть в этой строке: «metadata_entry = GetJsonString (пользователь, модуль, экспонента, электронная почта)». Я попробовал код построчно, и в этой строке возникает ошибка.
2. @MarvinHauser Вы уверены, что модуль и показатель степени являются строками? base64.encode возвращает байты из объекта, подобного байту. Вам нужно будет вернуть modulus.encode(‘utf80),exponent(‘utf8’) в getModulusExponentInBase64 — скажите мне, в чем проблема, и я обновлю ответ.