ansible / awx

AWX provides a web-based user interface, REST API, and task engine built on top of Ansible. It is one of the upstream projects for Red Hat Ansible Automation Platform.
Other
14.06k stars 3.42k forks source link

Adding vault KV backed machine credential and prompting for ssh key unlock process is awkward and painful #4876

Open omgjlk opened 5 years ago

omgjlk commented 5 years ago
ISSUE TYPE
SUMMARY

The process to create and configure a machine credential programmatically is kind of awkward. As I understand it, one must:

This can all work via automation (Ansible itself) the first time though, and it results in a functional credential set. However the trouble is with the second run of the automation (hey it should be able to be run a bunch of times right?). The second step from above is ran and results in attempting to edit the machine credential, and seems to attempt to remove the "prompt for ssh key passphrase" setting, but does not remove the configured input source for ssh_key data. This throws an error: Response: {\"inputs\":{\"ssh_key_unlock\":[\"must be set when SSH key is encrypted.\"]}}

ENVIRONMENT
STEPS TO REPRODUCE

See the above summary.

EXPECTED RESULTS

I would like to be able to automate creation and updating of these credentials. I'd prefer not to have to jump through a bunch of hoops, checking to see if the credential exists before creating it for the first time with empty data.

ACTUAL RESULTS

Errors, unless I only do the initial creation once.

ADDITIONAL INFORMATION

I realize that this is new feature and functionality, and that I'm making it more complicated by wanting to prompt for the SSH key unlock passphrase. I'm happy to work with developers on testing possible solutions. I can share my automation too if desired, once scrubbed of sensitive data.

omgjlk commented 5 years ago

Here is the example tasks I've come up with to deal with this:

# Deal with Vault backed credentails
# Due to https://github.com/ansible/awx/issues/4876 this takes effort
# First we need to check of a vault backed cred exists
# Then create our vault backed machine credential if it doesn't exist,
# with blank data.
# Then create the vault cred itself, and link it to the input source
# of the machine credential.
# Finally we set the rest of the data on the machine credential.

    - name: Get vault backed credentials
      command:
        argv:
          - /data/awx/virtualenv/bin/awx
          - credential
          - list
          - -f
          - json
          - --name
          - "{{ item.name }}"
      register: vbcreds
      loop: "{{ vault_backed_credentials }}"
      # AWX cli does not read tower config file, so set env vars
      environment:
        TOWER_USERNAME: "{{ tower_username }}"
        TOWER_PASSWORD: "{{ tower_password }}"
        TOWER_HOST: "{{ tower_host }}"

    - name: Configure initial vault backed credentials
      tower_credential:
        kind: "{{ item.0.kind }}"
        name: "{{ item.0.name }}"
        tower_host: "{{ tower_host }}"
        tower_password: "{{ tower_password }}"
        tower_username: "{{ tower_username }}"
        tower_verify_ssl: "{{ tower_verify_ssl }}"
        state: "{{ item.state |default('present') }}"
        organization: "{{ item.0.organization }}"
      loop: "{{ vault_backed_credentials |zip(vbcreds.results) |list }}"
      when: (item.1.stdout |from_json)['count'] == 0

    - block:
        # Do this w/ awx cli as the ansible module does not support this type
      - name: Configure Hashicorp Vault credential
        command:
          argv:
            - /data/awx/virtualenv/bin/awx
            - credential
            - create
            - --name
            - "{{ item.name }}"
            - --organization
            - "{{ item.organization }}"
            - --credential_type
            - "{{ item.kind }}"
            - --inputs
            - "{{ item.inputs |to_json }}"
            - -f
            - human
        register: vcout
        failed_when: vcout.rc != 0 and 'Duplicate' not in vcout.stdout
        no_log: true
        loop: "{{ vault_credentials }}"

      # Have to know the actual ID of source_credential and target_credential
      # see https://github.com/ansible/awx/issues/4874
      - name: Get target credential IDs
        command:
          argv:
            - /data/awx/virtualenv/bin/awx
            - credential
            - get
            - "{{ item.name }}"
            - -f
            - json
        register: tuid
        loop: "{{ vault_backed_credentials }}"

      - name: Get source credential IDs
        command:
          argv:
            - /data/awx/virtualenv/bin/awx
            - credential
            - get
            - "{{ item.name }}"
            - -f
            - json
        register: suid
        no_log: true
        loop: "{{ vault_credentials }}"

      - name: Configure user credential inputs
        command:
          argv:
            - /data/awx/virtualenv/bin/awx
            - credential_input_sources
            - create
            - --target_credential
            - "{{ (item.1.stdout |from_json)['id'] }}"
            - --input_field_name
            - "{{ item.0.input_field_name }}"
            - --source_credential
            - "{{ (suid.results[0]['stdout'] |from_json)['id'] }}"
            - --metadata
            - "{{ item.0.metadata |to_json }}"
            - -f
            - human
        register: ucout
        failed_when: ucout.rc != 0 and 'Duplicate' not in ucout.stdout
        loop: "{{ user_credential_inputs |zip(tuid.results) |list }}"

      # AWX cli does not read tower config file, so set env vars
      environment:
        TOWER_USERNAME: "{{ tower_username }}"
        TOWER_PASSWORD: "{{ tower_password }}"
        TOWER_HOST: "{{ tower_host }}"

    - name: Update Vault backed creds
      tower_credential:
        kind: "{{ item.kind }}"
        name: "{{ item.name }}"
        username: "{{ item.username |default(omit) }}"
        description: "{{ item.description |default(omit) }}"
        tower_host: "{{ tower_host }}"
        team: "{{ item.team |default(omit) }}"
        tower_password: "{{ tower_password }}"
        tower_username: "{{ tower_username }}"
        password: "{{ item.password |default(omit) }}"
        tower_verify_ssl: "{{ tower_verify_ssl }}"
        state: "{{ item.state |default('present') }}"
        ssh_key_data: "{{ item.ssh_key_data |default(omit) }}"
        ssh_key_unlock: ASK
        organization: "{{ item.organization }}"
      loop: "{{ vault_backed_credentials }}"
Saurabh-Thakre commented 4 years ago

Able to reproduce this issue. Here are the steps.

ssh-keygen -f ~/mykey

must be set when SSH key is encrypted.

mwmahlberg commented 4 years ago

I would kindly suggest to increase the priority since it is security-related.

igormaksimoff commented 3 years ago

For AWX 19.4.0 it is still and issue.

Halytskyi commented 1 year ago

AWX 21.10.2 and still the issue

in0ps commented 1 year ago

AWX 23.2.0 the issue still occur

rev138 commented 3 months ago

24.6.1-- still broken