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

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 '-',

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.