0

I need an automated job to perform REST API calls against Foreman and would much rather not bother setting up an account for it -- and then forever maintain the password.

However, it appears, Foreman has only an "all or nothing" -- if the authentication is required for anything (:login: true), then it will be required for everything.

Is that really true, or is the appearance deceiving and Foreman can be told to allow anonymous lookups and host-browsing, while still requiring authentication for any changes?

1 Answer 1

1

Ok, it turns out, Foreman supports the OAuth1 kind of access, which is not much (or even any) better than simply a static username/password. Worse, unless you take special measures by mapping such access to an unprivileged account, connections using OAuth1 will have admin-privileges.

Visit the settings page of your Foreman-installation to turn on the mapping and/or learn/set the OAuth1 "key" and "secret" strings.

While the real users may be authenticating via LDAP (such as against your corporate Active Directory) or other means, the OAuth1-using script can use the same "key" and "secret" values for ever -- they don't even expire.

Edit: enabling user-mapping does not appear to improve security at all -- any existing account-name can be specified and no knowledge of the account's password or any other secrets is necessary.

My simple Foreman-search script implemented in Python is thus (no support for pagination -- all my queries return well under 50 entries):

from requests_oauthlib import OAuth1Session
import json
import sys

search=sys.argv[1]
fields=sys.argv[2:]
if not fields:
    fields = ['ip']

URL=("https://foreman.example.net/api/v2/hosts?search=%s" % search)

# The below highly-secret credentials come from
#
#   https://foreman.example.net/settings
#
Key='mykey'
Secret='mysecret'
User='readonly'

session=OAuth1Session(Key, Secret)
# The FOREMAN-USER header is necessary, if mapping of OAuth-requests is
# turned on in Foreman's settings. The username must exist and have the
# right "roles" enabled to allow the account to perform the request.
session.headers.update({'FOREMAN-USER': User})

request=session.get(URL, verify='/path/to/your/CA/certificate.crt')

if not request.ok:
    request.raise_for_status()

response=json.loads(request.content)
results=response["results"]

for i in xrange(0, response["subtotal"]):
    entry=results[i]
    if i > 0:
        print
    for field in fields:
        try:
            print entry[field],
        except KeyError:
        print '-',

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .