issue with service account key
SUMMARY
Hi, I'm running into a problem with gcp_iam_service_account_key...each time I try what's explained on the documentation (here: https://docs.ansible.com/ansible/latest/collections/google/cloud/gcp_iam_service_account_key_module.html#ansible-collections-google-cloud-gcp-iam-service-account-key-module), I get the same error :
File is not a valid GCP JSON service account key
ISSUE TYPE
- Bug Report
COMPONENT NAME
gcp_iam_service_account_key
ANSIBLE VERSION
ansible 2.9.6
config file = /etc/ansible/ansible.cfg
configured module search path = ['/home/mike/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3/dist-packages/ansible
executable location = /usr/bin/ansible
python version = 3.8.5 (default, Jul 28 2020, 12:59:40) [GCC 9.3.0]
CONFIGURATION
ACTION_WARNINGS(default) = True
AGNOSTIC_BECOME_PROMPT(default) = True
ALLOW_WORLD_READABLE_TMPFILES(default) = False
ANSIBLE_CONNECTION_PATH(default) = None
ANSIBLE_COW_PATH(default) = None
ANSIBLE_COW_SELECTION(default) = default
ANSIBLE_COW_WHITELIST(default) = ['bud-frogs', 'bunny', 'cheese', 'daemon', 'default', 'dragon', 'elephant-in-snake', 'elephant', 'eyes', 'hellokitty', 'kitty', 'luke-koala', 'meow', 'milk', 'moofasa', 'moose', 'ren', 'sheep', 'small', '
stegosaurus', 'stimpy', 'supermilker', 'three-eyes', 'turkey', 'turtle', 'tux', 'udder', 'vader-koala', 'vader', 'www']
ANSIBLE_FORCE_COLOR(default) = False
ANSIBLE_NOCOLOR(default) = False
ANSIBLE_NOCOWS(default) = False
ANSIBLE_PIPELINING(default) = False
ANSIBLE_SSH_ARGS(default) = -C -o ControlMaster=auto -o ControlPersist=60s
ANSIBLE_SSH_CONTROL_PATH(default) = None
ANSIBLE_SSH_CONTROL_PATH_DIR(default) = ~/.ansible/cp
ANSIBLE_SSH_EXECUTABLE(default) = ssh
ANSIBLE_SSH_RETRIES(default) = 0
ANY_ERRORS_FATAL(default) = False
BECOME_ALLOW_SAME_USER(default) = False
BECOME_PLUGIN_PATH(default) = ['/home/mike/.ansible/plugins/become', '/usr/share/ansible/plugins/become']
CACHE_PLUGIN(default) = memory
CACHE_PLUGIN_CONNECTION(default) = None
CACHE_PLUGIN_PREFIX(default) = ansible_facts
CACHE_PLUGIN_TIMEOUT(default) = 86400
COLLECTIONS_PATHS(default) = ['/home/mike/.ansible/collections', '/usr/share/ansible/collections']
COLOR_CHANGED(default) = yellow
COLOR_CONSOLE_PROMPT(default) = white
COLOR_DEBUG(default) = dark gray
COLOR_DEPRECATE(default) = purple
COLOR_DIFF_ADD(default) = green
COLOR_DIFF_LINES(default) = cyan
COLOR_DIFF_REMOVE(default) = red
COLOR_ERROR(default) = red
COLOR_HIGHLIGHT(default) = white
COLOR_OK(default) = green
COLOR_SKIP(default) = cyan
COLOR_UNREACHABLE(default) = bright red
COLOR_VERBOSE(default) = blue
COLOR_WARN(default) = bright purple
COMMAND_WARNINGS(default) = True
CONDITIONAL_BARE_VARS(default) = True
CONNECTION_FACTS_MODULES(default) = {'eos': 'eos_facts', 'frr': 'frr_facts', 'ios': 'ios_facts', 'iosxr': 'iosxr_facts', 'junos': 'junos_facts', 'nxos': 'nxos_facts', 'vyos': 'vyos_facts'}
COVERAGE_REMOTE_OUTPUT(default) = None
COVERAGE_REMOTE_WHITELIST(default) = *
DEFAULT_ACTION_PLUGIN_PATH(default) = ['/home/mike/.ansible/plugins/action', '/usr/share/ansible/plugins/action']
DEFAULT_ALLOW_UNSAFE_LOOKUPS(default) = False
DEFAULT_ASK_PASS(default) = False
DEFAULT_ASK_VAULT_PASS(default) = False
DEFAULT_BECOME(default) = False
DEFAULT_BECOME_ASK_PASS(default) = False
DEFAULT_BECOME_EXE(default) = None
DEFAULT_BECOME_FLAGS(default) =
DEFAULT_BECOME_METHOD(default) = sudo
DEFAULT_BECOME_USER(default) = root
DEFAULT_CACHE_PLUGIN_PATH(default) = ['/home/mike/.ansible/plugins/cache', '/usr/share/ansible/plugins/cache']
DEFAULT_CALLABLE_WHITELIST(default) = []
DEFAULT_CALLBACK_PLUGIN_PATH(default) = ['/home/mike/.ansible/plugins/callback', '/usr/share/ansible/plugins/callback']
DEFAULT_CALLBACK_WHITELIST(default) = []
OS / ENVIRONMENT
I'm on Ubuntu 20.04
STEPS TO REPRODUCE
main.yml
- name: "create service Account"
gcp_iam_service_account:
name: "gcp-{{ environments }}-{{ buckets }}-sa@{{ project }}.iam.gserviceaccount.com"
display_name: "gcp-{{ environments }}-{{ buckets }}-sa"
project: "{{ project }}"
auth_kind: serviceaccount
service_account_file: "tf-project-1351-3278615fdb7b.json"
state: present
with_items:
- buckets
register: serviceaccount
- name: "Create Service Account Key file"
gcp_iam_service_account_key:
service_account: "{{ serviceaccount }}"
# key_algorithm: "KEY_ALG_RSA_2048"
private_key_type: TYPE_GOOGLE_CREDENTIALS_FILE
path: "{{ project }}.json"
project: "{{ project }}"
auth_kind: serviceaccount
service_account_file: "tf-project-1351-3278615fdb7b.json"
state: present
with_items:
- buckets
vars.yml
environments: "dev"
buckets: orga
project: "tf-project-1351"
EXPECTED RESULTS
Get the json key from google service account
ACTUAL RESULTS
The full traceback is:
File "/tmp/ansible_gcp_iam_service_account_key_payload_14828lgb/ansible_gcp_iam_service_account_key_payload.zip/ansible/modules/cloud/google/gcp_iam_service_account_key.py", line 240, in key_name_from_file
File "/usr/lib/python3.8/json/__init__.py", line 357, in loads
return _default_decoder.decode(s)
File "/usr/lib/python3.8/json/decoder.py", line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib/python3.8/json/decoder.py", line 355, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
failed: [localhost] (item=buckets) => {
"ansible_loop_var": "item",
"changed": false,
"invocation": {
"module_args": {
"auth_kind": "serviceaccount",
"env_type": null,
"key_algorithm": null,
"path": "tf-project-1351.json",
"private_key_type": "TYPE_GOOGLE_CREDENTIALS_FILE",
"project": "tf-project-1351",
"scopes": [
"https://www.googleapis.com/auth/iam"
],
"service_account": {
"changed": false,
"msg": "All items completed",
"results": [
{
"ansible_loop_var": "item",
"changed": false,
"displayName": "gcp-dev-orga-sa",
"email": "[email protected]",
"etag": "MDEwMjE5MjA=",
"failed": false,
"invocation": {
"module_args": {
"auth_kind": "serviceaccount",
"display_name": "gcp-dev-orga-sa",
"env_type": null,
"name": "[email protected]",
"project": "tf-project-1351",
"scopes": [
"https://www.googleapis.com/auth/iam"
],
"service_account_contents": null,
"service_account_email": null,
"service_account_file": "tf-project-1351-3278615fdb7b.json",
"state": "present"
}
},
"item": "buckets",
"name": "[email protected]",
"oauth2ClientId": "106591229016502380749",
"projectId": "tf-project-1351",
"uniqueId": "106591229016502380749"
}
]
},
"service_account_contents": null,
"service_account_email": null,
"service_account_file": "tf-project-1351-3278615fdb7b.json",
"state": "present"
}
},
"item": "buckets",
"msg": "File is not a valid GCP JSON service account key"
}
Ran into this problem. You have to delete the file in the path attribute before running the key generation (if it already exists) or the module tries to read it. Try adding this first:
- name: Remove creds file if exists
ansible.builtin.file:
path: "{{ project }}.json"
state: absent
Google, please fix the documentation to make it clear it would read the file if it exists already.
This ansible module is not idempotent. And there's no reason nor technical impediment for this module to be idempotent.
If no key was retrieved, why write an empty file?
If no key was retrieved, why write an empty file?
The module IIUC does not write an empty file. Instead, if a user creates a file there that is not json, the the module attempts to read it.
I've file #576 to update documentation to note the behavior around the file. If there's a better way to handle these, we're definitely open to PRs!