Is it possible to pass cypher defined in master tenant to an Ansible task in a subtenant?
The example given in the note is executed by morpheus before the task is run. The replacement in a bash script occurs before the execution of that bash script. In an Ansible task, youâre using a cypher lookup that uses an API key injected into the ansible run task. If that ephemeral runtime API key has access to the cypher item to be decrypted then it will work, but otherwise, it wonât. Long story short, I donât think itâll work if the cypher key is in a different tenant.
@ncelebic I know the native cypher var supports a â<%=cypher.read(âsecret/testâ,true)%>â that works to this extent. Iâm assuming the cypher lookup would have to be updated to support this?
@ncelebic we are experiencing indeed similar behaviour.
We are running against the same âissueâ in a production setup. Itâs not an issue for us though, as we just add in the cypher keys inside each tenant and all seems to work.
Example:
- We define a instance type at the master tenant level. (Example nginx server)
- We attach a workflow to this instance type item that runs in the Provision step an Ansible task that queries a Cypher key.
Example: cypher.yml
---
- name: Playbook to test Cypher
gather_facts: false
hosts: all
tasks:
- name: Print MorpheusData Cypher secret/helloworld
debug:
msg: "Value for the key secret/helloworld equals to '{{ lookup('cypher','secret=secret/helloworld') }}''"
When provisioning an instance based on this instance type from the master level we will receive the output for the Ansible task:
TASK [Print MorpheusData Cypher secret/helloworld] *****************************
ok: [nginx-123.localdomain] => {
"msg": "Value for the key secret/helloworld equals to 'This is a demo secret called 'secret/helloworld'''"
}
When we pull this instance type to a sub tenant and provision an instance based on this we get:
TASK [Print MorpheusData Cypher secret/helloworld] *****************************
fatal: [nginx-acme-123.localdomain]: FAILED! => {"msg": "An unhandled exception occurred while running the lookup plugin 'cypher'. Error was a <class 'ansible.errors.AnsibleError'>, original message: The secret secret/helloworld doesn't seem to exist for cypher lookup"}
Thus far, I suppose behaviour to be expected.
Changing the code to append a âtrueâ parameter (in analogy to the native cypher read) to the lookup in Ansible doesnât seem to crash the command and it seems to execute, but the results do stay the same.
- name: Print MorpheusData Cypher secret/helloworld
debug:
msg: "Value for the key secret/helloworld equals to '{{ lookup('cypher','secret=secret/helloworld', 'true') }}''"
The lookup is being referenced here: Ansible â Morpheus Docs documentation
But I canât see from the docs if with Ansible the cypher values can be pulled through the tenancy structure.
EDIT:
The only way I managed to work around this, at the moment, is by querying the Cypher API with a user who has access to this secret. This seems to be working in a sub tenant.
An example would be (data is in the âkeyresult.dataâ dictionary).
---
- name: Playbook to access Cypher from master level
gather_facts: false
hosts: all
tasks:
- name: Login to Morpheus
uri:
url: "{{ vars.morpheus.morpheus.applianceUrl }}oauth/token?grant_type=password&scope=write&client_id=morph-api"
method: POST
validate_certs: no
body_format: form-urlencoded
body:
- [ username, myusername]
- [ password, mypassword ]
status_code: 200
register: logindata
- name: Get Cypher key
uri:
url: "{{vars.morpheus.morpheus.applianceUrl }}api/cypher/v1/secret/helloworld"
validate_certs: no
return_content: true
headers:
Content-Type: application/json
Authorization: "BEARER {{ logindata.json.access_token }}"
register: keyresult
- name: Print MorpheusData Cypher secret/helloworld
debug:
msg: "Value for the key secret/helloworld equals to '{{ keyresult }}''"
Same question.
How this can be used in ansible? (not API call).
PASSWORD=<%=cypher.read(âsecret/myuserpasswordâ,true)%> works in bash scripts, file templates but not when running on ansible.
I believe the ansible cypher lookup would need to be updated to support this. @ncelebic may be able to add additional insight.
Currently, the only workaround I found (until this is changed) is to log in as a user from the appropriate tenant with Ansible, fetch the Cypher value and then use it in the sub tenant. (As described above)
Currently, the only workaround I found (until this is changed) is to log in as a user from the appropriate tenant with Ansible, fetch the Cypher value and then use it in the sub tenant. (As described above)
This causes concerns with security, it requires to keep your access tokens, passwords in a code. Thatâs not secure wise.
I believe the ansible cypher lookup would need to be updated to support this. @ncelebic may be able to add additional insight.
We had raised a case for that Almost 2 years ago ( Created At
8/21/2020) and guess what, it was converted to feature request and is still not resolved
Feature request: MFR133607
Cypher lookups in Ansible occur during Ansible runtime. The solution above for bash works because itâs evaluated prior to runtime. If thereâs an external way to access cypher keys that arenât in your tenant in runtime, you could do it from anywhere with access to the Morpheus API, which would cause a security issue.
I may be overthinking it, but this would probably require an upstream Morpheus change for a flag for a particular Cypher key to be accessible from other tenants, and it might tie in with more granular RBAC.
Hi,
As a Morpheus user myself itâs unfortunate to hear about it being this long. But we often do notice ourselves that Ansible is an entire different beast with its caveats and itâs own lifecycle (which has its advantages but also its downsides).
There are also perhaps some other workarounds possible (havenât tested these yet):
- store the access credential to a user which can access the master tenant cypher key inside each sub tenant.
I know itâs a bit circular, but it doesnât require storing sensitive credentials in code.
- Temporarily pull the credentials from the master tenant to the sub tenant cypher store with a bash script and store it in the sub tenant cypher, use it and then delete it.
Downside is that if Cypher access is possible for users in the sub tenant, this could lead to a small timeframe of exposing credentials. For us this would work, as we only distribute Cypher access to restricted accounts in a sub tenants that are only used for maintenance.
That is until it gets solved. If you are interested in any of those routes, happy to test them out and report back.
A Cypher policy could be set in each Sub-Tenant restricting access to only a specific user/role/group to lock it down further if needed.