GithubHelp home page GithubHelp logo

jamf / jawa Goto Github PK

View Code? Open in Web Editor NEW
127.0 18.0 12.0 3.36 MB

Jamf Automation and Webhook Assistant

License: MIT License

Python 32.17% CSS 8.00% HTML 50.92% Shell 8.92%
jamf jamfpro webhooks automation jss timed scheduling scripts macadmins cronjob-scheduler

jawa's Introduction

Jamf Automation and Webhook Assistant ("JAWA") Version 3.1.0

JAWA allows an IT Administrator to focus on providing the best end user experience through automation.

[!] NOTE: Always test automations in a dev/eval environment before deploying to production.

What is JAWA?

JAWA, the Jamf Automation and Webhook Assistant, is a web server designed to streamline automation workflows with Jamf Pro and other services. It features a webhook receiver for real-time automation and a crontab for scheduled script execution and report generation. JAWA simplifies the creation of time-saving workflows for Jamf Pro admins, providing a user-friendly framework to connect multiple services seamlessly within an organization.

Check out JAWA on the Jamf Marketplace for screenshots.

Server Requirements

General Server Requirements:

  • Ubuntu 20.04+ or RHEL 8.x+
  • Minimum: 8GB RAM (16GB recommended)
  • Minimum: 128GB Storage (512GB recommended)
  • Minimum: 2 CPU Core (4 Cores recommended)
  • Python 3.8+ (with pip)

Network Requirements:

  • Inbound port 443 from JPS for webhooks (IPs for Jamf Cloud)
  • Optional: Inbound port 443 from your LAN/IP (for web console access)
  • Outbound port 443 to JPS and auxiliary services ( Okta, WorkDay, etc.)
  • A public DNS entry for the JAWA FQDN

Certificate Requirements:

  • Jamf Pro connects to JAWA over HTTPS to send webhooks. JAWA must present a valid certificate for Jamf Pro to trust the connection.
  • A Publicly Trusted SSL Certificate and corresponding private key (for nginx)
    • Note: A Publicly Trusted Full-chain Certificate is preferred for jawa.crt(i.e., root CA + intermediate + leaf cert bundle)

Jamf Pro Requirements:

  • Jamf Pro Server 10.35.0+

How to Use JAWA

Refer to the "JAWA Administrators Guide" in the current release for detailed installation and configuration instructions.

Installation Steps:

  1. Verify that you meet the server requirements.

  2. Rename the certificate to jawa.crt and the private key to jawa.key.

  3. Ensure you are in the same directory as your jawa.crt and jawa.key.

  4. Download and run the JAWA installer:

    curl -O https://raw.githubusercontent.com/jamf/JAWA/master/bin/installer.sh && sudo bash ./installer.sh
  5. After the installation is complete, go to your FQDN (e.g., https://jawa.company.com) in your web browser to continue with the web-based setup.

Configuration Steps:

  1. Log in to JAWA with your Jamf Pro URL and Jamf Pro Administrator Credentials.
  2. Click the “Setup link in the JAWA Dashboard or click Setup in the top navigation.
  3. Fill out the Server Setup form:
    • [required] JAWA Server Address FQDN (e.g., https://jawa.company.com) - this address must be resolvable by the Jamf Pro Server to send webhooks.
    • [recommended] Lock your JAWA to a primary Jamf Pro Server.
    • [optional] Add an alternate Jamf Pro Server.
  4. Click Setup.
  5. Set up your first webhook or timed automation.

When scripting for webhooks, verify JSON structure sent from source:

  1. Jamf Pro Webhook Event Info
  2. Okta Webhook Event Info

Releases

Find JAWA releases here.

JAWA v3.1.0 release

  • New features
    • enhanced UI, mobile-friendly view
    • unified installer
    • enhanced script cleanup routine
  • Bugfixes
    • improved error handling
    • sanitized user inputs to prevent XSS exploits
    • unified installer that does not overwrite nginx defaults (resolving #31)
    • general bugfix and maintenance

jawa's People

Contributors

ball42 avatar jamfmatt avatar matthewsphillips avatar ropelletier avatar yuresko avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jawa's Issues

Invalid cookie header

JAWA seems to be causing a lot of warning messages in the Jamf Pro Server Log (please see below). Would this be possible to fix?

2022-01-20 08:47:30,806 [WARN ] [alPool-1915] [ResponseProcessCookies ] - Invalid cookie header: "Set-Cookie: session=; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Max-Age=0; Path=/". Invalid 'expires' attribute: Thu, 01 Jan 1970 00:00:00 GMT

Incompatibility with Flask 3.x and Werkzeug 3.x

While configuring a new JAWA server today on RHEL, I ran into these errors when starting the jawa service (copied from journalctl -u jawa.service):

ImportError: cannot import name 'escape' from 'flask' (/usr/local/jawa/venv/lib64/python3.9/site-packages/flask/init.py)

and

ImportError: cannot import name 'url_quote' from 'werkzeug.urls' (/usr/local/jawa/venv/lib64/python3.9/site-packages/werkzeug/urls.py)

This resulted in a 502 Bad Gateway error when trying to load the HTTPS site.

Comparing the output of /usr/local/jawa/venv/bin/pip3 list on my working dev server to my non-working new server, I found that the working server was running Flask 2.2.2 and Werkzeug 2.2.2, while the failing server had version 3.0 of each.

After downgrading both packages like so...

/usr/local/jawa/venv/bin/pip3 install Flask==2.2.2
/usr/local/jawa/venv/bin/pip3 install Werkzeug==2.2.2

...and then rebooting the server, the site is up and running.

As a quick fix, I suggest specifying the version of these libraries in requirements.txt so new installs will work. Long-term, ideally JAWA could be updated to support the newer libraries.

Feature Request: webhook authentication

As of now, webhooks created by JAWA do not appear to use authentication when communicating to the JAWA server. This appears to be a security risk, as those with the right URL can anonymously have the JAWA server perform the actions defined by that web hook.

I would like to request randomized credentials be set up as part of each webhook, so that both username and password are randomly generated for each webhook. That way, one compromised webhook would not compromise all.

RHEL installer modifies the default nginx.conf

I've noticed that the installer script for RHEL and CentOS modifies the default nginx.conf:

JAWA/bin/rhel_installer.sh

Lines 331 to 334 in fbfdaf1

if [ -e /etc/nginx/nginx.conf ]; then
/usr/bin/rm /etc/nginx/nginx.conf
fi
cat << EOF >> /etc/nginx/nginx.conf

Modifying the default config file could cause problems with multi-application deployments or existing proxy servers.

Instead, this script should act similar to Ubuntu with a small tweak. In Ubuntu, nginx modular configurations are loaded from /etc/nginx/conf.d/*.conf and /etc/nginx/sites-enabled/*.conf; the latter is loaded to provide a similar interface to Apache2 in Debian and Ubuntu. In RHEL, only /etc/nginx/conf.d/*.conf is loaded by default. This comes from the default config file's line include /etc/nginx/conf.d/*.conf;.

Therefore, JAWA should place its modular configuration inside the /etc/nginx/conf.d/ directory.

Problems launching JAWA 3.0.2 with newer Python

I've tried to get JAWA 3.0.2 to launch with a newer version of Python installed (3.9 or 3.10) on Ubuntu 18.04.

Sep 12 10:40:53 jawa python3[3142]: File "/usr/local/bin/jawa/app.py", line 5, in
Sep 12 10:40:53 jawa systemd[1]: jawa.service: Main process exited, code=exited, status=1/FAILURE
Sep 12 10:40:53 jawa systemd[1]: jawa.service: Failed with result 'exit-code'.
Sep 12 10:40:54 jawa systemd[1]: jawa.service: Service hold-off time over, scheduling restart.
Sep 12 10:40:54 jawa systemd[1]: jawa.service: Scheduled restart job, restart counter is at 1.

Am I doing something wrong?

Setting unique wallpaper per device

Apologies if this should not belong here, but I am hoping to get some assistance. I have been trying to configure custom wallpaper for each of our iOS devices. Unfortunately, I am unable to even get my test to work. I did post something in the community and opened up a ticket with JAMF, but have not had any answers so far. Here is the community post: https://community.jamf.com/t5/jamf-pro/jamf-pro-api-wallpaper-base64-encoded-giving-an-error-problem/td-p/301599

My goal was to rewrite this in python (My skillset is PHP, not python, which is why my proof of concept is in PHP, but I can manage). That being said, it would be amazing if PHP were also an option in JAWA.

I have watched the section of the YouTube demonstration here: https://www.youtube.com/watch?v=GicgP0tgwyM&ab_channel=Jamf
Specifically the section dealing with Unique wallpaper, but it would be very helpful if you could share the auto_wallpaper.py script. That would be very appreciated and a great first step to trying to figure out why this does not work. Thank you for your time and insight.

HTTP Basic authentication is deprecated in the Jamf Classic API

According to Basic Authentication - Classic API Authentication Changes on the Jamf API documentation, HTTP Basic authentication to the Classic API is deprecated and could be removed from Jamf as early as August.

There appear to be a couple of places where JAWA uses Basic authentication:

JAWA/views/jamf_webhook.py

Lines 383 to 390 in fbfdaf1

full_url = f"{session['url']}/JSSResource/webhooks/id/{each_webhook.get('jamf_id')}"
jawa_logger().info(f"{session.get('username')} editing the JPS webhook {name}.")
try:
webhook_response = requests.put(full_url,
auth=(session['username'], session['password']),
headers={'Content-Type': 'application/xml'}, data=data,
verify=verify_ssl)

full_url = f"{session['url']}/JSSResource/webhooks/name/{each_webhook['name']}"
webhook_response = requests.put(full_url,
auth=(session['username'], session['password']),
headers={'Content-Type': 'application/xml'},
data=data)

For JAMF versions >=10.35.0, JAWA can use a bearer token instead. The login route should be changed to post to /v1/auth/token. The generated token and its expiry time can be stored in the client-side session cookie (which is how the username and password are stored right now). The wrinkle, then, is getting JAWA to renew the token when needed. Either on every request or when the token is close to expiring, request /v1/auth/keep-alive to get a new token and store it in the cookie.

Updating SSL/TLS certificate

Hello!

If I need to update my SSL/TLS certificate and private key, what is the best way to accomplish this?

Thank you.

Possibility to send a custom response to POST requests for custom webhooks

I've got a non-Jamf Pro system on which I've created a webhook in. When that webhook is triggered I want it to send a POST request to JAWA, which will run a script that collects information from Jamf Pro.

So I've created a custom webhook in JAWA and the non-Jamf Pro system is able to send a POST request to JAWA which JAWA receives. So far so good. The problem now is that I want to send a custom JSON response to that POST request based on the output of the script being executed by JAWA. But it seems that JAWA is only returning the original JSON string that was sent with the POST request from the non-Jamf Pro system when it responds with HTTP 200 OK on a successful POST request.

Would it be possible to change so that the response is the output of the script that is being executed for the custom webhook in JAWA? Or at least make it optional to return the script output as response?

My Python scripting skills are not very good, but I've looked at jawa_receiver.py and it could look something like this (not tested):

if validate_webhook(webhook_data, webhook_name, webhook_user, webhook_pass):
    jawa_logger().info(f"{webhook_name} validated!")
    run_script(webhook_data, webhook_name)

    for each_webhook in webhooks_json:
      if each_webhook['name'] == webhook_name:
        if each_webhook['tag'] == "custom":
          return run_script(webhook_data, webhook_name), 200
else:
    jawa_logger().info(f"{webhook_name} not validated!")
    return "Unauthorized", 401

return webhook_data, 200

There's probably a much more efficient way to return the output of the script than to run the script one more time via the run_script function though.

This would be really helpfully! I really appreciate that JAWA exists! :)

Installer needs to check for existing crontab entries before adding

After multiple installations of the CentOS version of JAWA, I now have multiple crontab entries:

sudo crontab -l
@reboot /usr/bin/python /usr/local/jawa/webapp.py
@reboot /usr/bin/webhook -hooks /etc/webhook.conf -secure -cert /usr/local/jawa/security/combocert.pem -key /usr/local/jawa/security/jawa.key -verbose -hotreload
@reboot /usr/bin/python /usr/local/jawa/webapp.py
@reboot /usr/bin/webhook -hooks /etc/webhook.conf -secure -cert /usr/local/jawa/security/combocert.pem -key /usr/local/jawa/security/jawa.key -verbose -hotreload
@reboot /usr/bin/python /usr/local/jawa/webapp.py
@reboot /usr/bin/webhook -hooks /etc/webhook.conf -secure -cert /usr/local/jawa/security/combocert.pem -key /usr/local/jawa/security/jawa.key -verbose -hotreload
@reboot /usr/bin/python /usr/local/jawa/webapp.py
@reboot /usr/bin/webhook -hooks /etc/webhook.conf -secure -cert /usr/local/jawa/security/combocert.pem -key /usr/local/jawa/security/jawa.key -verbose -hotreload
@reboot /usr/bin/python /usr/local/jawa/webapp.py
@reboot /usr/bin/webhook -hooks /etc/webhook.conf -secure -cert /usr/local/jawa/security/combocert.pem -key /usr/local/jawa/security/jawa.key -verbose -hotreload
@reboot /usr/bin/python /usr/local/jawa/webapp.py
@reboot /usr/bin/webhook -hooks /etc/webhook.conf -secure -cert /usr/local/jawa/security/combocert.pem -key /usr/local/jawa/security/jawa.key -verbose -hotreload
@reboot /usr/bin/python /usr/local/jawa/webapp.py
@reboot /usr/bin/webhook -hooks /etc/webhook.conf -secure -cert /usr/local/jawa/security/combocert.pem -key /usr/local/jawa/security/jawa.key -verbose -hotreload
@reboot /usr/bin/python /usr/local/jawa/webapp.py
@reboot /usr/bin/webhook -hooks /etc/webhook.conf -secure -cert /usr/local/jawa/security/combocert.pem -key /usr/local/jawa/security/jawa.key -verbose -hotreload
@reboot /usr/bin/python /usr/local/jawa/webapp.py
@reboot /usr/bin/webhook -hooks /etc/webhook.conf -secure -cert /usr/local/jawa/security/combocert.pem -key /usr/local/jawa/security/jawa.key -verbose -hotreload
@reboot /usr/bin/python /usr/local/jawa/webapp.py
@reboot /usr/bin/webhook -hooks /etc/webhook.conf -secure -cert /usr/local/jawa/security/combocert.pem -key /usr/local/jawa/security/jawa.key -verbose -hotreload
@reboot /usr/bin/python /usr/local/jawa/webapp.py
@reboot /usr/bin/webhook -hooks /etc/webhook.conf -secure -cert /usr/local/jawa/security/combocert.pem -key /usr/local/jawa/security/jawa.key -verbose -hotreload
@reboot /usr/bin/python /usr/local/jawa/webapp.py
@reboot /usr/bin/webhook -hooks /etc/webhook.conf -secure -cert /usr/local/jawa/security/combocert.pem -key /usr/local/jawa/security/jawa.key -verbose -hotreload
@reboot /usr/bin/python /usr/local/jawa/webapp.py
@reboot /usr/bin/webhook -hooks /etc/webhook.conf -secure -cert /usr/local/jawa/security/combocert.pem -key /usr/local/jawa/security/jawa.key -verbose -hotreload
@reboot /usr/bin/python /usr/local/jawa/webapp.py
@reboot /usr/bin/webhook -hooks /etc/webhook.conf -secure -cert /usr/local/jawa/security/combocert.pem -key /usr/local/jawa/security/jawa.key -verbose -hotreload
@reboot /usr/bin/python /usr/local/jawa/webapp.py
@reboot /usr/bin/webhook -hooks /etc/webhook.conf -secure -cert /usr/local/jawa/security/combocert.pem -key /usr/local/jawa/security/jawa.key -verbose -hotreload
@reboot /usr/bin/python /usr/local/jawa/webapp.py
@reboot /usr/bin/webhook -hooks /etc/webhook.conf -secure -cert /usr/local/jawa/security/combocert.pem -key /usr/local/jawa/security/jawa.key -verbose -hotreload

webhook-auth branch crons

It seems the crons on the webhook-auth branch are still using absolute paths instead of the new relative paths under the "data" folder. Is this expected to be fixed sometime?

ImportError: cannot import name 'escape' from 'flask'

Received the following error after install. Jawa service will not start

Oct 11 13:24:29 cms-jawa1 python3[4739]: Traceback (most recent call last):
Oct 11 13:24:29 cms-jawa1 python3[4739]:   File "/usr/local/jawa/jawa/app.py", line 35, in <module>
Oct 11 13:24:29 cms-jawa1 python3[4739]:     from flask import (Flask, request, render_template,
Oct 11 13:24:29 cms-jawa1 python3[4739]: ImportError: cannot import name 'escape' from 'flask' (/usr/local/jawa/jawa/venv/lib/python3.10/site-packages/flask/__init__.py)
Oct 11 13:24:29 cms-jawa1 systemd[1]: jawa.service: Main process exited, code=exited, status=1/FAILURE
Oct 11 13:24:29 cms-jawa1 systemd[1]: jawa.service: Failed with result 'exit-code'.
Oct 11 13:24:30 cms-jawa1 systemd[1]: jawa.service: Scheduled restart job, restart counter is at 2.
Oct 11 13:24:30 cms-jawa1 systemd[1]: Stopped Jamf Automation & Webhooks Assistant.
Oct 11 13:24:30 cms-jawa1 systemd[1]: Started Jamf Automation & Webhooks Assistant.
Oct 11 13:24:30 cms-jawa1 python3[4740]: Traceback (most recent call last):
Oct 11 13:24:30 cms-jawa1 python3[4740]:   File "/usr/local/jawa/jawa/app.py", line 35, in <module>
Oct 11 13:24:30 cms-jawa1 python3[4740]:     from flask import (Flask, request, render_template,
Oct 11 13:24:30 cms-jawa1 python3[4740]: ImportError: cannot import name 'escape' from 'flask' (/usr/local/jawa/jawa/venv/lib/python3.10/site-packages/flask/__init__.py)
Oct 11 13:24:30 cms-jawa1 systemd[1]: jawa.service: Main process exited, code=exited, status=1/FAILURE
Oct 11 13:24:30 cms-jawa1 systemd[1]: jawa.service: Failed with result 'exit-code'.
Oct 11 13:24:30 cms-jawa1 systemd[1]: jawa.service: Scheduled restart job, restart counter is at 3.
Oct 11 13:24:30 cms-jawa1 systemd[1]: Stopped Jamf Automation & Webhooks Assistant.
Oct 11 13:24:30 cms-jawa1 systemd[1]: Started Jamf Automation & Webhooks Assistant.

Error occurred: 401 Client Error

After our Jamf Pro instance was updated to 10.47, I started to see these errors, I am running in docker and have tried rebuilding it with he same results.

running /usr/bin/curl -s -X POST "https://xx.jamfcloud.com/api/v1/auth/token" -H "Authorization: Basic base64" in the console I get the token.

/usr/local/jawa/app.py:35: DeprecationWarning: 'flask.escape' is deprecated and will be removed in Flask 2.4. Import 'markupsafe.escape' instead.
from flask import (Flask, request, render_template,
INFO:jawa.views.home_view:[https://XX.jamfcloud.com] Attempting login for: jamfapi-account
INFO:jawa.views.home_view:Error occurred: 401 Client Error: for url: https://XX.jamfcloud.com/JSSResource/activationcode
INFO:jawa.bin.tokens:[https://XX.jamfcloud.com] Successfully invalidated token for logout.
INFO:jawa.views.home_view:Logging Out: jamfapi-account
INFO:jawa.views.home_view:[https://XX.jamfcloud.com] Attempting login for: jamfapi-rw
INFO:jawa.views.home_view:Error occurred: 401 Client Error: for url: https://XX.jamfcloud.com/JSSResource/activationcode
INFO:jawa.bin.tokens:[https://XX.jamfcloud.com] Successfully invalidated token for logout.
INFO:jawa.views.home_view:Logging Out: jamfapi-account

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.