ansible-collections / community.general

Ansible Community General Collection
https://galaxy.ansible.com/ui/repo/published/community/general/
GNU General Public License v3.0
838 stars 1.54k forks source link

gitlab_user module doesn't update SSH key for existing user #6516

Open sjaakvandenberg opened 1 year ago

sjaakvandenberg commented 1 year ago

Summary

When I try to update the SSH key for an existing Gitlab CE user using the gitlab_user module from the general collection (4.8.0), the change is not detected and the SSH keys aren't updated.

Issue Type

Bug Report

Component Name

gitlab_user

Ansible Version

$ ansible --version
ansible [core 2.11.10] 
  config file = /home/svdb/.ansible.cfg
  configured module search path = ['/home/svdb/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/svdb/tmp/venv/lib/python3.10/site-packages/ansible
  ansible collection location = /home/svdb/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/svdb/tmp/venv/bin/ansible
  python version = 3.10.6 (main, Mar 10 2023, 10:55:28) [GCC 11.3.0]
  jinja version = 3.1.2
  libyaml = False

Community.general Version

$ ansible-galaxy collection list community.general
# /home/svdb/.ansible/collections/ansible_collections
Collection        Version
----------------- -------
community.general 4.8.0

Configuration

$ ansible-config dump --only-changed
DEFAULT_LOG_PATH(/home/svdb/.ansible.cfg) = /var/log/ansible.log
DEFAULT_UNDEFINED_VAR_BEHAVIOR(/home/svdb/.ansible.cfg) = False
DEFAULT_VAULT_PASSWORD_FILE(env: ANSIBLE_VAULT_PASSWORD_FILE) = /home/svdb/.dev_password
DEPRECATION_WARNINGS(/home/svdb/.ansible.cfg) = False
HOST_KEY_CHECKING(/home/svdb/.ansible.cfg) = False
RETRY_FILES_ENABLED(/home/svdb/.ansible.cfg) = False

OS / Environment

Rocky 8

Steps to Reproduce

Example playbook:

---
- hosts: localhost
  connection: local
  gather_facts: no

  tasks:
    - name: update gitlab user
      gitlab_user:
        validate_certs: False
        api_url: "https://project.url:443"
        api_token: "glpat-QQwqab8asgBDwoeG8-8j"
        name: "Admin Two"
        username: "admin2"
        email: "admin2@project.url"
        sshkey_name: pubkey
        sshkey_file: "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILufIEYZNc81ipIXPYjlhOADEPRxkviJY7GKqrW0D3dI 20230510b"
        state: present
        confirm: no
        isadmin: yes
      register: res
    - debug: var=res

Existing user in Gitlab CE project with username admin2 and no SSH keys.

$ (venv) $ curl -sk -X GET --header "Authorization: Bearer glpat-QQwqab8asgBDwoeG8-8j" "https://project.url:443/api/v4/users/35/keys" | jq
[]

Run 1 (SSH key is set for the first time):

(venv) $ ansible-playbook play.yml
[WARNING]: log file at /var/log/ansible.log is not writeable and we cannot create it, aborting

[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] ****************************************************************************************************************************************************************************

TASK [update gitlab user] *******************************************************************************************************************************************************************
changed: [localhost]

TASK [debug] ********************************************************************************************************************************************************************************
ok: [localhost] => {
    "res": {
        "changed": true,
        "failed": false,
        "msg": "Successfully created or updated the user admin2",
        "user": {
            "avatar_url": "https://secure.gravatar.com/avatar/24423aff46d903b9e22ca0f350bc6e62?s=80&d=identicon",
            "bio": "",
            "bot": false,
            "can_create_group": true,
            "can_create_project": true,
            "color_scheme_id": 1,
            "commit_email": "admin2@project.url",
            "confirmed_at": "2023-05-01T18:33:41.567+02:00",
            "created_at": "2023-05-01T18:33:41.588+02:00",
            "created_by": {
                "avatar_url": "https://secure.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
                "id": 1,
                "name": "Administrator",
                "state": "active",
                "username": "root",
                "web_url": "https://project.url/root"
            },
            "current_sign_in_at": null,
            "discord": "",
            "email": "admin2@project.url",
            "external": false,
            "extra_shared_runners_minutes_limit": null,
            "followers": 0,
            "following": 0,
            "id": 35,
            "identities": [],
            "is_admin": true,
            "is_followed": false,
            "job_title": "",
            "last_activity_on": null,
            "last_sign_in_at": null,
            "linkedin": "",
            "local_time": null,
            "location": "",
            "name": "Admin Two",
            "namespace_id": 35,
            "note": null,
            "organization": "",
            "private_profile": false,
            "projects_limit": 100000,
            "pronouns": null,
            "public_email": null,
            "shared_runners_minutes_limit": null,
            "skype": "",
            "state": "active",
            "theme_id": 1,
            "twitter": "",
            "two_factor_enabled": false,
            "username": "admin2",
            "using_license_seat": false,
            "web_url": "https://project.url/admin2",
            "website_url": "",
            "work_information": null
        }
    }
}

PLAY RECAP **********************************************************************************************************************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
(venv) $ curl -sk -X GET --header "Authorization: Bearer glpat-QQwqab8asgBDwoeG8-8j" "https://project.url:443/api/v4/users/35/keys" | jq
[
  {
    "id": 13,
    "title": "pubkey",
    "created_at": "2023-05-10T16:09:05.750+02:00",
    "expires_at": null,
    "key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILufIEYZNc81ipIXPYjlhOADEPRxkviJY7GKqrW0D3dI Admin Two (project.url)",
    "usage_type": "auth_and_signing"
  }
]

RUN 2 (after updating SSH pubkey in play.yml)

(venv) $ ansible-playbook play.yml
[WARNING]: log file at /var/log/ansible.log is not writeable and we cannot create it, aborting

[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAY [localhost] ****************************************************************************************************************************************************************************

TASK [update gitlab user] *******************************************************************************************************************************************************************
ok: [localhost]

TASK [debug] ********************************************************************************************************************************************************************************
ok: [localhost] => {
    "res": {
        "changed": false,
        "failed": false,
        "msg": "No need to update the user admin2",
        "user": {
            "avatar_url": "https://secure.gravatar.com/avatar/24423aff46d903b9e22ca0f350bc6e62?s=80&d=identicon",
            "bio": "",
            "bot": false,
            "can_create_group": true,
            "can_create_project": true,
            "color_scheme_id": 1,
            "commit_email": "admin2@project.url",
            "confirmed_at": "2023-05-01T18:33:41.567+02:00",
            "created_at": "2023-05-01T18:33:41.588+02:00",
            "created_by": {
                "avatar_url": "https://secure.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
                "id": 1,
                "name": "Administrator",
                "state": "active",
                "username": "root",
                "web_url": "https://project.url/root"
            },
            "current_sign_in_at": null,
            "discord": "",
            "email": "admin2@project.url",
            "external": false,
            "extra_shared_runners_minutes_limit": null,
            "followers": 0,
            "following": 0,
            "id": 35,
            "identities": [],
            "is_admin": true,
            "is_followed": false,
            "job_title": "",
            "last_activity_on": null,
            "last_sign_in_at": null,
            "linkedin": "",
            "local_time": null,
            "location": "",
            "name": "Admin Two",
            "namespace_id": 35,
            "note": null,
            "organization": "",
            "private_profile": false,
            "projects_limit": 100000,
            "pronouns": null,
            "public_email": null,
            "shared_runners_minutes_limit": null,
            "skype": "",
            "state": "active",
            "theme_id": 1,
            "twitter": "",
            "two_factor_enabled": false,
            "username": "admin2",
            "using_license_seat": false,
            "web_url": "https://project.url/admin2",
            "website_url": "",
            "work_information": null
        }
    }
}

PLAY RECAP **********************************************************************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
(venv) $ curl -sk -X GET --header "Authorization: Bearer glpat-QQwqab8asgBDwoeG8-8j" "https://project.url:443/api/v4/users/35/keys" | jq
[
  {
    "id": 13,
    "title": "pubkey",
    "created_at": "2023-05-10T16:09:05.750+02:00",
    "expires_at": null,
    "key": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILufIEYZNc81ipIXPYjlhOADEPRxkviJY7GKqrW0D3dI Admin Two (project.url)",
    "usage_type": "auth_and_signing"
  }
]

Expected Results

I expected the SSH pubkey of the admin2 user would update the existing key (with comment 20230510b) to the new key (with comment 20230510c).

Actual Results

(venv) $ ansible-playbook play.yml -vvvv
[WARNING]: log file at /var/log/ansible.log is not writeable and we cannot create it, aborting

ansible-playbook [core 2.11.10]
  config file = /home/svdb/.ansible.cfg
  configured module search path = ['/home/svdb/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/svdb/tmp/venv/lib/python3.10/site-packages/ansible
  ansible collection location = /home/svdb/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/svdb/tmp/venv/bin/ansible-playbook
  python version = 3.10.6 (main, Mar 10 2023, 10:55:28) [GCC 11.3.0]
  jinja version = 3.1.2
  libyaml = False
Using /home/svdb/.ansible.cfg as config file
setting up inventory plugins
host_list declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Skipping due to inventory source not existing or not being readable by the current user
script declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
auto declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Skipping due to inventory source not existing or not being readable by the current user
yaml declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Skipping due to inventory source not existing or not being readable by the current user
ini declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Skipping due to inventory source not existing or not being readable by the current user
toml declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
redirecting (type: modules) ansible.builtin.gitlab_user to community.general.gitlab_user
Loading collection community.general from /home/svdb/.ansible/collections/ansible_collections/community/general
Loading callback plugin default of type stdout, v2.0 from /home/svdb/tmp/venv/lib/python3.10/site-packages/ansible/plugins/callback/default.py
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.

PLAYBOOK: play.yml **************************************************************************************************************************************************************************
Positional arguments: play.yml
verbosity: 4
connection: smart
timeout: 10
become_method: sudo
tags: ('all',)
inventory: ('/etc/ansible/hosts',)
forks: 5
1 plays in play.yml

PLAY [localhost] ****************************************************************************************************************************************************************************
META: ran handlers

TASK [update gitlab user] *******************************************************************************************************************************************************************
task path: /home/svdb/dev/poc/gitlab-user-module/play.yml:7
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: svdb
<127.0.0.1> EXEC /bin/sh -c 'echo ~svdb && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/svdb/.ansible/tmp `"&& mkdir "` echo /home/svdb/.ansible/tmp/ansible-tmp-1683729281.748694-277961-38869753003260 `" && echo ansible-tmp-1683729281.748694-277961-38869753003260="` echo /home/svdb/.ansible/tmp/ansible-tmp-1683729281.748694-277961-38869753003260 `" ) && sleep 0'
redirecting (type: modules) ansible.builtin.gitlab_user to community.general.gitlab_user
Using module file /home/svdb/.ansible/collections/ansible_collections/community/general/plugins/modules/gitlab_user.py
<127.0.0.1> PUT /home/svdb/.ansible/tmp/ansible-local-277954vis0fegd/tmprsk55799 TO /home/svdb/.ansible/tmp/ansible-tmp-1683729281.748694-277961-38869753003260/AnsiballZ_gitlab_user.py
<127.0.0.1> EXEC /bin/sh -c 'chmod u+x /home/svdb/.ansible/tmp/ansible-tmp-1683729281.748694-277961-38869753003260/ /home/svdb/.ansible/tmp/ansible-tmp-1683729281.748694-277961-38869753003260/AnsiballZ_gitlab_user.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '/home/svdb/tmp/venv/bin/python /home/svdb/.ansible/tmp/ansible-tmp-1683729281.748694-277961-38869753003260/AnsiballZ_gitlab_user.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'rm -f -r /home/svdb/.ansible/tmp/ansible-tmp-1683729281.748694-277961-38869753003260/ > /dev/null 2>&1 && sleep 0'
ok: [localhost] => {
    "changed": false,
    "invocation": {
        "module_args": {
            "access_level": "guest",
            "api_job_token": null,
            "api_oauth_token": null,
            "api_password": null,
            "api_token": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "api_url": "https://project.url:443",
            "api_username": null,
            "confirm": false,
            "email": "admin2@project.url",
            "external": false,
            "group": null,
            "identities": null,
            "isadmin": true,
            "name": "Admin Two",
            "overwrite_identities": false,
            "password": null,
            "reset_password": false,
            "sshkey_expires_at": null,
            "sshkey_file": "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPIaTZwcBi8bgM/DrGJ7RqK7bQDdEeXQPBZGgSF1owY/ 20230510c",
            "sshkey_name": "pubkey",
            "state": "present",
            "username": "admin2",
            "validate_certs": false
        }
    },
    "msg": "No need to update the user admin2",
    "user": {
        "avatar_url": "https://secure.gravatar.com/avatar/24423aff46d903b9e22ca0f350bc6e62?s=80&d=identicon",
        "bio": "",
        "bot": false,
        "can_create_group": true,
        "can_create_project": true,
        "color_scheme_id": 1,
        "commit_email": "admin2@project.url",
        "confirmed_at": "2023-05-01T18:33:41.567+02:00",
        "created_at": "2023-05-01T18:33:41.588+02:00",
        "created_by": {
            "avatar_url": "https://secure.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
            "id": 1,
            "name": "Administrator",
            "state": "active",
            "username": "root",
            "web_url": "https://project.url/root"
        },
        "current_sign_in_at": null,
        "discord": "",
        "email": "admin2@project.url",
        "external": false,
        "extra_shared_runners_minutes_limit": null,
        "followers": 0,
        "following": 0,
        "id": 35,
        "identities": [],
        "is_admin": true,
        "is_followed": false,
        "job_title": "",
        "last_activity_on": null,
        "last_sign_in_at": null,
        "linkedin": "",
        "local_time": null,
        "location": "",
        "name": "Admin Two",
        "namespace_id": 35,
        "note": null,
        "organization": "",
        "private_profile": false,
        "projects_limit": 100000,
        "pronouns": null,
        "public_email": null,
        "shared_runners_minutes_limit": null,
        "skype": "",
        "state": "active",
        "theme_id": 1,
        "twitter": "",
        "two_factor_enabled": false,
        "username": "admin2",
        "using_license_seat": false,
        "web_url": "https://project.url/admin2",
        "website_url": "",
        "work_information": null
    }
}

TASK [debug] ********************************************************************************************************************************************************************************
task path: /home/svdb/dev/poc/gitlab-user-module/play.yml:21
ok: [localhost] => {
    "res": {
        "changed": false,
        "failed": false,
        "msg": "No need to update the user admin2",
        "user": {
            "avatar_url": "https://secure.gravatar.com/avatar/24423aff46d903b9e22ca0f350bc6e62?s=80&d=identicon",
            "bio": "",
            "bot": false,
            "can_create_group": true,
            "can_create_project": true,
            "color_scheme_id": 1,
            "commit_email": "admin2@project.url",
            "confirmed_at": "2023-05-01T18:33:41.567+02:00",
            "created_at": "2023-05-01T18:33:41.588+02:00",
            "created_by": {
                "avatar_url": "https://secure.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon",
                "id": 1,
                "name": "Administrator",
                "state": "active",
                "username": "root",
                "web_url": "https://project.url/root"
            },
            "current_sign_in_at": null,
            "discord": "",
            "email": "admin2@project.url",
            "external": false,
            "extra_shared_runners_minutes_limit": null,
            "followers": 0,
            "following": 0,
            "id": 35,
            "identities": [],
            "is_admin": true,
            "is_followed": false,
            "job_title": "",
            "last_activity_on": null,
            "last_sign_in_at": null,
            "linkedin": "",
            "local_time": null,
            "location": "",
            "name": "Admin Two",
            "namespace_id": 35,
            "note": null,
            "organization": "",
            "private_profile": false,
            "projects_limit": 100000,
            "pronouns": null,
            "public_email": null,
            "shared_runners_minutes_limit": null,
            "skype": "",
            "state": "active",
            "theme_id": 1,
            "twitter": "",
            "two_factor_enabled": false,
            "username": "admin2",
            "using_license_seat": false,
            "web_url": "https://project.url/admin2",
            "website_url": "",
            "work_information": null
        }
    }
}
META: ran handlers
META: ran handlers

PLAY RECAP **********************************************************************************************************************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Code of Conduct

ansibullbot commented 1 year ago

Files identified in the description:

If these files are incorrect, please update the component name section of the description or use the !component bot command.

click here for bot help

ansibullbot commented 1 year ago

cc @LennertMertens @Lunik @Shaps @dj-wasabi @lgatellier @marwatk @metanovii @nejch @scodeman @sh0shin @stgrace @suukit @waheedi @zanssa click here for bot help

russoz commented 1 year ago

hi @sjaakvandenberg Thanks for reporting this issue.

That version of community.general is way too old. Could you please try and replicate the problem using the most recent version (7.1.0)? Thanks in advance.

ap-wtioit commented 1 year ago

As described in #7220 i got the same issue, the ssh key is not updated if it uses the same name.

As a workaround: In your playbook you use sshkey_name: pubkey for all keys (20230510c, 20230510b and "Admin Two (project.url)"). If you give them different names this should still work with the current implementation.