API OAuth

There is two legged OAuth protocol added in API allowing request authentication.

Signed request with OAuth (using oauth_consumer_key and oauth_consumer_secret) are trusted by Foreman. If request verification is successful a Foreman user is authenticated. Depending on oauth_map_users option the incoming request is executed as admin or as mapped user. If oauth_map_users is enabled users are mapped by User#login passed in X-FOREMAN-USER header.

Setup

  1. go to http://foreman.url/settings?utf8=%E2%9C%93&search=+category++%3D++Auth
  2. enable OAuth authetication oauth_active, set to true
  3. set oauth_consumer_key and oauth_consumer_secret
  4. optionally set oauth_map_users to true to enable user mapping

Troubleshooting

  • if you have trouble enabling OAuth authentication watch Foreman log WARN messages.
  • or debug OAuth authentication logic, see: source:lib/api/authorization.rb

Security

OAuth does not signs whole request (body and FOREMAN-USER are not signed), Api should be exposed over HTTPS.

Examples

To list architectures using curl

curl -X GET 'https://foreman.example.tst/api/v2/architectures' -H 'Content-Type: application/json' -H 'ForemanApiVersion: 2' \
-H 'Authorization: OAuth oauth_version="1.0",oauth_consumer_key="a",oauth_signature_method="hmac-sha1",oauth_signature="PlLTrHk5+aMgJACtww61dqakAWg=' -H 'FOREMAN-USER: ares'

oauth_consumer_key is set to a, oauth_map_users is enabled so we set FOREMAN-USER header. The signature is normally computed by oauth client library, in this case I got it from server, it uses following algorithm

base = [method, normalized_uri, normalized_parameters]
base = base.map { |v| escape(v) }.join("&")
Base64.encode64(base).chomp.gsub(/\n/,'')

as you can see, only method, URI and parameters are signed and verified on server side. Note that in real world usage, you should also include oauth_timestamp and oauth_nonce headers to prevent replay attacks.