【问题标题】:Google Cloud Function for creating windows vm password automatically用于自动创建 windows vm 密码的谷歌云功能
【发布时间】:2020-12-31 06:07:19
【问题描述】:

我尝试创建一个 Google Cloud Function 来自动为我的 vm 实例创建 Windows 密码。我找到了这个链接:https://cloud.google.com/compute/docs/instances/windows/automate-pw-generation#python

不幸的是,我经常使用 Javascript,因此我需要 Java、Python 或 Go 方面的帮助。在这种情况下,我决定使用 python 但没关系。

我的设置是: 运行时:Python 3.7 入口点:主要

代码

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}')

如您所见,我在 main 函数中添加了我的详细信息,我的 requirements.txt 如下所示:

pycrypto==2.6.1
oauth2client==4.1.3

不幸的是,它不起作用,我收到以下错误:

字节类型的对象不是 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(compute, instance, zone, project)”收到错误:

错误解码模数:输入字节 1 处的 base64 数据非法

【问题讨论】:

    标签: java python go google-cloud-platform google-cloud-functions


    【解决方案1】:

    您的函数不起作用,因为您使用的是 Python 2.x print 语句而不是 python3 print() 函数。

    替换

    print 'Username:   {0}'.format(user)
    

    print ('Username:   {0}'.format(user))
    

    您也可以使用 python 3.6+ f-strings 代替 format()

    pring(f'Username:    {user}')
    

    【讨论】:

    • 感谢您的回复。这是正确的。谢谢你。不幸的是,出现了另一个错误:“字节类型的对象不是 JSON 可序列化的”。问题必须在这一行:“metadata_entry = GetJsonString(用户,模数,指数,电子邮件)”。我逐行尝试了代码,在这一行中发生了错误。
    • @MarvinHauser 你确定模数和指数是字符串吗? base64.encode 从类似字节的对象返回字节。您需要在 getModulusExponentInBase64 中返回 modules.encode('utf80),exponent('utf8') - 告诉我这是否是问题所在,我会更新答案。
    猜你喜欢
    • 2021-10-12
    • 1970-01-01
    • 1970-01-01
    • 2017-11-14
    • 2020-05-21
    • 2018-12-11
    • 1970-01-01
    • 2020-04-02
    • 2019-04-06
    相关资源
    最近更新 更多