1

I am using the Google API Explorer in Python to manage service accounts and push new keys. That would be the method documented here: https://developers.google.com/resources/api-libraries/documentation/iam/v1/python/latest/iam_v1.projects.serviceAccounts.keys.html#upload

After I generated a key following the required convention (X509_PEM format) I call the method upload() like in the sample below.

import googleapiclient.discovery
from google.oauth2 import service_account

if __name__ == "__main__":
    
    credentials = service_account.Credentials.from_service_account_file(
        filename="path/to/credentials.json",
        scopes=["https://www.googleapis.com/auth/cloud-platform"]
    )
    iam_service = googleapiclient.discovery.build("iam", "v1", credentials=credentials)

    public_key = "-----BEGIN CERTIFICATE-----\nMIIFDDCCAvQCCQD3eTyPcnYUejANBgkqhkiG9w0BAQUFADBIMUYwRAYDVQQDDD10\nYW5ndXktYWJlbC1zYUBhaWdueC10ZXN0LWNsb3VkLXNldHVwLmlhbS5nc2Vydmlj\nZWFjY291bnQuY29tMB4XDTIyMDIwOTE2MzkyMFoXDTIzMDIwOTE2MzkyMFowSDFG\nMEQGA1UEAww9dGFuZ3V5LWFiZWwtc2FAYWlnbngtdGVzdC1jbG91ZC1zZXR1cC5p\nYW0uZ3NlcnZpY2VhY2NvdW50LmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC\nAgoCggIBAJimPN7VYTGikobRD6E29crjdKgB1H3uSh+ViHHGLVjuwMtBVafXeiEB\nBAes/IXWUCOosLOG0HKi253+xqZAAleX5g9zFOvUMjhpdJydCVLOxVEs6EfjgikD\nU8eiaUJig4sO6VWMFLxELOkMPmKfQN8ASE0ZG/j20tez4/Refo5YqN3Fkt6WNeiO\nrQ69KpcGRGPgpo1oT0TViopkeQD+yNBfesXrrPpGYfzQxGKFzkVE5zTRiIBRAAhf\nrjfZnLK1rOUPp8ZMfrapZja5xT4sL7Ug2fKVtmULtJK5k9X36bpY6JbwTSPhyi/m\ncLw49XOpqfoBe03fxQJMes8VH1dwifBRi5wL2Q0s6Kq6s9ZFT3aWAO6WP+l1pVMA\nB605edOjgauMsdc/0Fky+IOrwnGTrAyekEfxb7zd1yr9t4d5x/WYQlRnhp9JjuS6\nvA5ZGmtn2NaqADWSJ4MuVY7j6Fn9WWQVokRnyb3DgbqhaDuLHN3H6wbgA8U+k0ou\nmEwOx4VllDkGzFw9xfZdU8jDJu7uM+00s/MHxX30wzdJwnWspBFIpmHhaQQOp2D6\nbsggo1Lzn4Xe94ozrhG6mFaoLopL+2SpjBK3LO1L3zMiH65VK3K/CDxZdrBfT5CC\nkOJzcBNQxc8a3bQFauZQ9ZAbx1/bFtALXYF/tDNwYh4TUAJuWj01AgMBAAEwDQYJ\nKoZIhvcNAQEFBQADggIBAHq9SlyKIJwEy5okpXBpKPm7oq+W4Sud7eQNoq+Vg95f\nr4R0crHjayj3GaFF5IC1NSq2WRoPqMVZ76uFHRZwnGTOqjIyty4fq8NSe7HJ2jak\nRdKBBdnxND+VJrsx8ACGA+GZcNw/s5huekduD22iU3dkDYhERDZUHHcTlakoJxTO\ndOpLcTzPtTcGOn/cerIpHS2Sdb05qnUicDuOCuD6sz7KufLAEzjKPfve7S7sUtGq\n7aqaGjZpR3xf5LkmQCYKwuaFoK3Vz96l3MgHzf2+dxezcDTfUnwU48es04PObasE\noeTlRGvlhkP2QZdlXaXcOZ83sDhgoYcqqaf2EoUm/ycYJ1QjKMw+mlCawx7I4HFi\n1cDt+xQXOlzI/0eEKhNSM7Vh7wZtzsedga5Pye+i3FqxK/tdoa3jCDmwLdoNps+W\nyrf7JdzSYqHILVSYt3CiUzKsgpyvtK/GDrhHsrIZM2oLQK+4auRSOrfW5x13v9pk\nlTUlkLEW0F3V5dhiToccYX+d/WG2pKEB/at8MSwTAvj/ZLhD7Q0oqrpAVSP0K4Lo\nhSkTRJov3fyWWfrsEsg7BEWy9iCJYbymy8NupFf6VJxBFdcME9F/pPI18v0hKa8T\nmA1ZcJLjPsZE0zmXtDfozlmZIXT2/wP+BKV8p2Rt7dZToMdBLbHc3wL3B9CpoiAM\n-----END CERTIFICATE-----"

    iam_service.projects().serviceAccounts().keys().upload(
        name="projects/my-cloud-project/serviceAccounts/[email protected]",
        body={
            "publicKeyData": public_key
        }).execute()

This call returns the following error:

<HttpError 400 when requesting https://iam.googleapis.com/v1/projects/aignx-test-cloud-setup/serviceAccounts/[email protected]/keys:upload?alt=json returned "Invalid value at 'public_key_data' (TYPE_BYTES), Base64 decoding failed for public_key = "-----BEGIN CERTIFICATE-----\nMIIFDDCCAvQCCQD3eTyPcnYUejANBgkqhkiG9w0BAQUFADBIMUYwRAYDVQQDDD10\nYW5ndXktYWJlbC1zYUBhaWdueC10ZXN0LWNsb3VkLXNldHVwLmlhbS5nc2Vydmlj\nZWFjY291bnQuY29tMB4XDTIyMDIwOTE2MzkyMFoXDTIzMDIwOTE2MzkyMFowSDFG\nMEQGA1UEAww9dGFuZ3V5LWFiZWwtc2FAYWlnbngtdGVzdC1jbG91ZC1zZXR1cC5p\nYW0uZ3NlcnZpY2VhY2NvdW50LmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCC\nAgoCggIBAJimPN7VYTGikobRD6E29crjdKgB1H3uSh+ViHHGLVjuwMtBVafXeiEB\nBAes/IXWUCOosLOG0HKi253+xqZAAleX5g9zFOvUMjhpdJydCVLOxVEs6EfjgikD\nU8eiaUJig4sO6VWMFLxELOkMPmKfQN8ASE0ZG/j20tez4/Refo5YqN3Fkt6WNeiO\nrQ69KpcGRGPgpo1oT0TViopkeQD+yNBfesXrrPpGYfzQxGKFzkVE5zTRiIBRAAhf\nrjfZnLK1rOUPp8ZMfrapZja5xT4sL7Ug2fKVtmULtJK5k9X36bpY6JbwTSPhyi/m\ncLw49XOpqfoBe03fxQJMes8VH1dwifBRi5wL2Q0s6Kq6s9ZFT3aWAO6WP+l1pVMA\nB605edOjgauMsdc/0Fky+IOrwnGTrAyekEfxb7zd1yr9t4d5x/WYQlRnhp9JjuS6\nvA5ZGmtn2NaqADWSJ4MuVY7j6Fn9WWQVokRnyb3DgbqhaDuLHN3H6wbgA8U+k0ou\nmEwOx4VllDkGzFw9xfZdU8jDJu7uM+00s/MHxX30wzdJwnWspBFIpmHhaQQOp2D6\nbsggo1Lzn4Xe94ozrhG6mFaoLopL+2SpjBK3LO1L3zMiH65VK3K/CDxZdrBfT5CC\nkOJzcBNQxc8a3bQFauZQ9ZAbx1/bFtALXYF/tDNwYh4TUAJuWj01AgMBAAEwDQYJ\nKoZIhvcNAQEFBQADggIBAHq9SlyKIJwEy5okpXBpKPm7oq+W4Sud7eQNoq+Vg95f\nr4R0crHjayj3GaFF5IC1NSq2WRoPqMVZ76uFHRZwnGTOqjIyty4fq8NSe7HJ2jak\nRdKBBdnxND+VJrsx8ACGA+GZcNw/s5huekduD22iU3dkDYhERDZUHHcTlakoJxTO\ndOpLcTzPtTcGOn/cerIpHS2Sdb05qnUicDuOCuD6sz7KufLAEzjKPfve7S7sUtGq\n7aqaGjZpR3xf5LkmQCYKwuaFoK3Vz96l3MgHzf2+dxezcDTfUnwU48es04PObasE\noeTlRGvlhkP2QZdlXaXcOZ83sDhgoYcqqaf2EoUm/ycYJ1QjKMw+mlCawx7I4HFi\n1cDt+xQXOlzI/0eEKhNSM7Vh7wZtzsedga5Pye+i3FqxK/tdoa3jCDmwLdoNps+W\nyrf7JdzSYqHILVSYt3CiUzKsgpyvtK/GDrhHsrIZM2oLQK+4auRSOrfW5x13v9pk\nlTUlkLEW0F3V5dhiToccYX+d/WG2pKEB/at8MSwTAvj/ZLhD7Q0oqrpAVSP0K4Lo\nhSkTRJov3fyWWfrsEsg7BEWy9iCJYbymy8NupFf6VJxBFdcME9F/pPI18v0hKa8T\nmA1ZcJLjPsZE0zmXtDfozlmZIXT2/wP+BKV8p2Rt7dZToMdBLbHc3wL3B9CpoiAM\n-----END CERTIFICATE-----"".

I am able to upload the same certificate using the gcloud cli:

gcloud iam service-accounts keys upload certificate.pem  --iam-account [email protected]  --project my-cloud-project --format json

I tried to adjust the format of the key I send within the payload in my Python code, but nothing goes through; I tried to strip the line breaks, with and without the wrapper. The documentation I linked above does not specify the excepted format in the payload. This documentation seems to describe the same format as the one I use: https://cloud.google.com/iot/docs/concepts/device-security#public_key_format

Any idea how I could fix my call? Thanks!

1 Answer 1

0

After analysing the payload sent by the gcloud command, I understood that the field publicKeyData must be base64-encoded. When looking at the error this actually makes sense. So that simply fixed it:

import base64
...

iam_service.projects().serviceAccounts().keys().upload(
        name="projects/my-cloud-project/serviceAccounts/[email protected]",
        body={
            "publicKeyData": base64.b64encode(public_key.encode("utf-8")).decode("utf-8")
        }).execute()

Note that the string is encoded, base64-encoded, then decoded again to be sent as a string and not bytes.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.