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!