Getting Data In

How do I allow users to edit credentials using the setup screen?

ralphmct
Path Finder

Does anyone know how to allow users to edit credentials using the setup screen? I've used the setup.xml to create a screen and the host/user/pass gets saved to the correct REST endpoint but if I go to create a new credential for the same host then I get an error because it already exists:

Encountered the following error while trying to update: In handler 'localapps': Error while posting to url=/servicesNS/nobody/myapp/storage/passwords

I need to allow users to update their credentials for a host in Splunk to stay in sync with the login details of the host, while also trying to prevent the user having to do a manual delete on the old credentials via REST or app.conf.

EDIT: I've tried * as below answer suggests but it doesn't work as intended. I also tried a custom entity but I got an error as I describe in the comments below. Any help appreciated

kathychurch
Explorer

I too had this same problem and tried all the suggestions above. The work-around I settled on was to keep the field type as "password" in setup.xml, but the actual create/update of the password in the password store was done in code in a custom endpoint. So only the password is in the password store, I kept the associated username in the conf file. If anyone has arrived at a better solution, I'd love to know.

setup.xml

<setup>    
 <block title="My Configuration" endpoint="admin/myconfig" entity="config">
      <input field="user">
      <label>Username</label>
      <type>text</type>
   </input>
      <input field="password">
      <label>Password</label>
      <type>password</type>
   </input>
    </block>
</setup>

myapp_handler.py

def handleEdit(self, confInfo):
    username = self.callerArgs.data['user'][0]
    password = self.callerArgs.data['password'][0]
    self.callerArgs.data['password'][0] = ''
    self.writeConf('resilient', 'config', self.callerArgs.data)

    r = requests.post(url=splunk.getLocalServerInfo()+'/servicesNS/nobody/myapp/storage/passwords/%3Amyapppassword%3A?output_mode=json',
        data={'password': password},
        headers={'Authorization': 'Splunk ' + self.getSessionKey()},
        verify=False)

kathychurch
Explorer

I forgot to mention, you will also probably need to add logic to your setup function check and see if there is an entry for 'myapppassword' in the password store, and if there isn't, add a placeholder one.

0 Karma

phoenixdigital
Builder

Thanks for this post it steered me in the right direction. Been battling the custom endpoints for a while now. They are very finicky and the splunkd logs don't give any hints as to where issues are.

# http://docs.splunk.com/Documentation/Splunk/6.5.1/RESTREF/RESTaccess#storage.2Fpasswords

# Check if password exists
url = splunk.getLocalServerInfo()+'/servicesNS/nobody/appName/storage/passwords/realmName%3A' + args["proxy_username"][0] + '%3A?output_mode=json'
r = requests.get(url=url,
    headers={'Authorization': 'Splunk ' + self.getSessionKey()},
    verify=False)

if r.status_code == 200:
    # Update in password store via REST interface
    url = splunk.getLocalServerInfo()+'/servicesNS/nobody/appName/storage/passwords/realmName%3A' + args["proxy_username"][0] + '%3A?output_mode=json'
    r = requests.post(url=url,
        data={'password': args["proxy_password"][0]},
        headers={'Authorization': 'Splunk ' + self.getSessionKey()},
        verify=False)

else:
    # Create in password store via REST interface (Will have no effect if the user exists)
    url = splunk.getLocalServerInfo()+'/servicesNS/nobody/appName/storage/passwords?output_mode=json'
    r = requests.post(url=url,
        data={'name': args["proxy_username"][0], 'password': args["proxy_password"][0], 'realm': "realmName"},
        headers={'Authorization': 'Splunk ' + self.getSessionKey()},
        verify=False)
0 Karma

Lowell
Super Champion

For anyone following along, here's a search you can use to find errors produced by a custom EAI script:

index=_internal sourcetype=splunkd AdminManagerExternal | rex mode=sed "s/\\\\n/\n/g"

0 Karma

bwooden
Splunk Employee
Splunk Employee

As discussed above, you can create new credentials via setup.xml like this:

<setup>
  <block title="Shiny New Credential" endpoint="storage/passwords" entity="_new">
    <input field="name">
      <label>Username</label>
      <type>text</type>
    </input>
    <input field="password">
      <label>Password</label>
      <type>password</type>
    </input>
  </block>
</setup>

Let's say I filled it in with username=tedward and password=2Cents. The result is stored in .../local/apps.conf (note the double colon :: between credential and tedward, that is where the realm would be stored, if we were using realm in this example, but we are not)

[credential::tedward:]
password = $1$KtY=

If we try to edit the tedward™ credential by filtering entity for tedward, like this (and hard code tedward into label):

<setup>
  <block title="Gently Used Credential" endpoint="storage/passwords" entity="tedward">
    <input field="password">
      <label>Password for tedward</label>
      <type>password</type>
    </input>
  </block>
</setup>

The error returned will be something similar to this: error Encountered the following error while trying to update: In handler 'localapps': Cannot find item for POST arg_name="/storage/passwords/%3Atedward%3A/password"


We still have one more option, we can disable eai_strict mode to access the username token and place an asterisk after the entity. Note if we had a realm called captain associated with this credential, we could narrow the scope by updating entity to captain:tedward*

<setup>
  <block title="Thread Bare Credential" endpoint="storage/passwords" entity="tedward*" mode="iter" eai_strict="false">
    <input field="password">
      <label>Password for $username$</label>
      <type>password</type>
    </input>
  </block>
 </setup>

References: THE blog on setup.xml & how to use it in your code. Gëzuar! Also, setup.xml.conf.spec

alacercogitatus
SplunkTrust
SplunkTrust

Most likely, your setup.xml is using entity=_new in the definition. Therefore, Splunk tries to create new, but already exists, so it fails. I think you will need to specify which entity you want to update, I haven't tested this.

<block title="Add Account Info" endpoint="admin/passwords" entity="USERNAME_HERE">
<input field="password">
<label>Password</label>
<type>password</type>
</input>
</block>

OR TRY

<block title="Add Account Info" endpoint="admin/passwords" entity="*">
<input field="name">
<label>Username</label>
<type>text</type>
</input>
<input field="password">
<label>Password</label>
<type>password</type>
</input>
</block>

0 Karma

ralphmct
Path Finder

Yep just tried it again and I get a 404 from Splunk because it has a problem with that entity - 'Splunk cannot find "apps/local/MyApp/setup".' I've gotten this error before when there are syntax problems with the setup.xml and splunkd.log also shows that it was a problem with the GET request for that entity because it doesn't exist yet.

0 Karma

tdepuy
Path Finder

I am getting this error as well. I get a big bad error message if I use "USERNAME_HERE" as @ralphmct I believe is referencing. If I use the * I get more and more password fields. I'm up to 7 now and if I go back to the _new and add a new username/password it seems to add another username/password entry. Did you guys find a way out of this?

0 Karma

ralphmct
Path Finder

Thanks for the answer. I tried entity="*" previously and it didn't quite solve the problem because it still created new entities on REST.

I also tried your first suggestion but couldn't get it to work - I can't remember exactly why but I think it was an issue of not having that entity available first time through

0 Karma
Did you miss .conf21 Virtual?

Good news! The event's keynotes and many of its breakout sessions are now available online, and still totally FREE!