How to authenticate to the MAAS API

Errors or typos? Topics missing? Hard to read? Let us know.

MAAS API utilises 0-legged OAuth for authentication. While some endpoints allow anonymous access, others require authenticated requests. This page provides examples in Python, Ruby, curl, and HTTP for fetching the list of nodes.

Python

The example employs the fades library, but you can also use requests_oauthlib and oauthlib. Replace <MAAS_SERVER_IP> and <API-KEY> with appropriate values.

from oauthlib.oauth1 import SIGNATURE_PLAINTEXT
from requests_oauthlib import OAuth1Session

MAAS_HOST = "http://<MAAS_SERVER_IP>:5240/MAAS"
CONSUMER_KEY, CONSUMER_TOKEN, SECRET = "<API-KEY>".split(":")

maas = OAuth1Session(CONSUMER_KEY, resource_owner_key=CONSUMER_TOKEN, resource_owner_secret=SECRET, signature_method=SIGNATURE_PLAINTEXT)
nodes = maas.get(f"{MAAS_HOST}/api/2.0/machines/", params={"op": "list_allocated"})
nodes.raise_for_status()
print(nodes.json())

Ruby

require 'oauth'
require 'oauth/signature/plaintext'

def perform_API_request(site, uri, key, secret, consumer_key)
    consumer = OAuth::Consumer.new(consumer_key, "", { :site => site, :scheme => :header, :signature_method => "PLAINTEXT"})
    access_token = OAuth::AccessToken.new(consumer, key, secret)
    return access_token.request(:get, uri)
end
response = perform_API_request("http://server:5240/MAAS/api/2.0", "/nodes/?op=list", "<key>", "<secret>", "consumer_key")

cURL

curl --header "Authorization: OAuth oauth_version=1.0, oauth_signature_method=PLAINTEXT, oauth_consumer_key=$API_KEY[1], oauth_token=$API_KEY[2], oauth_signature=&$API_KEY[3], oauth_nonce=$(uuidgen), oauth_timestamp=$(date +%s)" $MAAS_URL/MAAS/api/2.0/users/

HTTPie and fish

set API_KEY (string split : $API_KEY)
http $MAAS_URL/api/2.0/users/ Authorization:"OAuth oauth_version=1.0, oauth_signature_method=PLAINTEXT, oauth_consumer_key=$API_KEY[1], oauth_token=$API_KEY[2], oauth_signature=&$API_KEY[3], oauth_nonce=$(uuidgen), oauth_timestamp=$(date +%s)"

Your API key comprises <consumer_key>:<consumer_token>:<secret>; use it to perform authenticated requests.

This Python example does not seem to work in Python 3.

[nix-shell:~/maas-oauth]$ ./test.py
Traceback (most recent call last):
  File "/Users/jpparker/maas-oauth/./test.py", line 3, in <module>
    import oauth.oauth as oauth
  File "/nix/store/9bl1s62q3l3ndzci6681mh4v02gm6rnz-python3-3.9.10-env/lib/python3.9/site-packages/oauth/oauth.py", line 29, in <module>
    import urlparse
ModuleNotFoundError: No module named 'urlparse'

The “oauth” library used in the example last had a release in 2009. This was already reported (Working python oauth example) but it doesn’t look to have been fixed.

We updated this last year, it seems to ahve reverted. I will find out why.

@billwear for some reason, revision 8 was reverted. That revision had changes made by @sparkiegeek that moved away from the deprecated library and was in a working state. Can we please bring back that version? Not sure what happened.

In the meantime, this should work:

import oauth.oauth as oauth
import httplib2
import uuid

def perform_API_request(site, uri, method, key, secret, consumer_key):
    resource_tok_string = "oauth_token_secret=%s&oauth_token=%s" % (
        secret, key)
    resource_token = oauth.OAuthToken.from_string(resource_tok_string)
    consumer_token = oauth.OAuthConsumer(consumer_key, "")

    oauth_request = oauth.OAuthRequest.from_consumer_and_token(
        consumer_token, token=resource_token, http_url=site,
        parameters={'oauth_nonce': uuid.uuid4().hex})
    oauth_request.sign_request(
        oauth.OAuthSignatureMethod_PLAINTEXT(), consumer_token,
        resource_token)
    headers = oauth_request.to_header()
    url = "%s%s" % (site, uri)
    http = httplib2.Http()
    return http.request(url, method, body=None, headers=headers)

# API key = '<consumer_key>:<key>:<secret>'
response = perform_API_request(
    'http://server/MAAS/api/1.0', '/nodes/?op=list', 'GET', '<key>', '<secret>',
    '<consumer_key>')

yep, accidental regression. will fix today.

should be done. lmk if it’s not right.

1 Like

You can also make an API call with cURL or HTTPie.
To do this you need to manually craft a proper Authorization header.

Here is an example using fish and HTTPie:

set API_KEY (string split : $API_KEY)

http $MAAS_URL/api/2.0/users/ \
Authorization:"OAuth oauth_version=1.0, oauth_signature_method=PLAINTEXT, oauth_consumer_key=$API_KEY[1], oauth_token=$API_KEY[2], oauth_signature=&$API_KEY[3], oauth_nonce=$(uuidgen), oauth_timestamp=$(date +%s)"

With cURL it will be as simple as:

curl --header "Authorization: OAuth oauth_version=1.0, oauth_signature_method=PLAINTEXT, oauth_consumer_key=$API_KEY[1], oauth_token=$API_KEY[2], oauth_signature=&$API_KEY[3], oauth_nonce=$(uuidgen), oauth_timestamp=$(date +%s)" \
$MAAS_URL/MAAS/api/2.0/users/
1 Like

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.