Облачная функция Google для автоматического создания пароля виртуальной машины Windows

# #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 — скажите мне, в чем проблема, и я обновлю ответ.