JVM Garbage Collection and Optimizations

Image
Overview When troubleshooting systems for performance-related issues, memory optimizations are a place that needs a deep analysis of what each system stores in the memory, how long those are stored, and access patterns. This post is to keep a note on the background information and valuable points to note in such an effort, specific to Java-based implementations as a deep understanding of the JVM behaviors is very beneficial in the process.

Java language provides much convenience to the developers by taking care of the memory management to a great extent letting the focus be on the rest of the logic. Still having a good understanding of how Java does this underneath, rationalize several best practices we follow in Java implementations and help design the programs better and think seriously on some aspects that can later lead to memory leaks and system stability in the long run. Java Garbage Collector has a big role in this been responsible for freeing up memory by removing memory gar…

OPA for HTTP Authorization

Open Policy Agent[1] is a promising, light weight and very generic policy engine to govern authorization is any type of domain. I found this comparion[2] very attractive in evaluating OPA for a project I am currently working on, where they demonstrate how OPA can cater same functionality defined in RBAC, RBAC with Seperation of Duty, ABAC and XACML.  

Here are the steps to a brief demonstration of OPA used for HTTP API authorization based on the sample [3], taking it another level up.

Running OPA Server

First we need to download OPA from [4], based on the operating system we are running on. 
For linux, 
curl -L -o opa https://github.com/open-policy-agent/opa/releases/download/v0.10.3/opa_linux_amd64 
Make it executable,
chmod 755 ./opa
Once done, we can start OPA policy engine as a server.
./opa run --server

Define Data and Rules

Next we need to load data and authorization rules to the server, so it can make decisions. OPA defines these in files in the format of .rego. Below is a sample file I used.
package httpapi.authz

subordinates = {"alice": [], "charlie": [], "bob": ["alice"], "betty": ["charlie"]}

# HTTP API request
import input as http_api
# http_api = {
#   "path": ["finance", "salary", "alice"],
#   "user": "alice",
#   "method": "GET"
#   "user_agent": "cURL/1.0"
#   "remote_addr": "127.0.0.1"
# }

default allow = false

# Allow users to get their own salaries.
allow {
  http_api.method = "GET"
  http_api.path = ["finance", "salary", username]
  username = http_api.user
}

# Allow managers to get their subordinates' salaries.
allow {
  http_api.method = "GET"
  http_api.path = ["finance", "salary", username]
  subordinates[http_api.user][_] = username
}

# Allow managers to edit their subordinates' salaries only if the request came
# from user agent cURL and address 127.0.0.1.
allow {
  http_api.method = "POST"
  http_api.path = ["finance", "salary", username]
  subordinates[http_api.user][_] = username
  http_api.remote_addr = "127.0.0.1"
  http_api.user_agent = "curl/7.47.0"
}

At first it defines a data set, which represents the relationship subordinates. For example as per this dataset, alice is a subordinate of bob. Then it defines 3 rules that will give feedback as 'allow'.
  • If user tries to get own salary it is allowed.
  • If a user tries to get the salary of a subordinate it is allowed.
  • If a user tries to modify the salary, it is allowed only if it is of a subordinate, request is initiated from remote address '127.0.0.1' and user agent 'curl/7.47.0'
To load this policy into the OPA engine we use below call.
curl -X PUT --data-binary @salary-example.rego  localhost:8181/v1/policies/example
The above policy is stored into a file named 'salary-example.rego' and referred in the above command.

Evaluate at API Invocation

Below is a sample API implementation in python, that consults the OPA engine on the decision whether to provide a response or deny as unauthorized.

#!/usr/bin/env python

import base64
import os

from flask import Flask
from flask import request
import json
import requests

import logging
import sys
logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)

app = Flask(__name__)

opa_url = os.environ.get("OPA_ADDR", "http://localhost:8181")
policy_path = os.environ.get("POLICY_PATH", "/v1/data/httpapi/authz")

def check_auth(url, user, method, user_agent, remote_addr,url_as_array, token):
    input_dict = {"input": {
        "user": user,
        "path": url_as_array,
        "method": method,
    "user_agent": user_agent,
    "remote_addr": remote_addr
    }}
    if token is not None:
        input_dict["input"]["token"] = token

    logging.info("Checking auth...")
    logging.info(json.dumps(input_dict, indent=2))
    try:
        rsp = requests.post(url, data=json.dumps(input_dict))
    except Exception as err:
        logging.info(err)
        return {}
    if rsp.status_code >= 300:
        logging.info("Error checking auth, got status %s and message: %s" % (j.status_code, j.text))
        return {}
    j = rsp.json()
    logging.info("Auth response:")
    logging.info(json.dumps(j, indent=2))
    return j

@app.route('/', defaults={'path': ''}, methods = ['GET', 'POST', 'DELETE'])
@app.route('/<path:path>', methods = ['GET', 'POST'])
def root(path):
    user_encoded = request.headers.get('Authorization', "Anonymous:none")
    logging.info("User Agent: %s" % request.user_agent.string)
    logging.info("Remote Address: %s" % request.remote_addr)
    if user_encoded:
        user_encoded = user_encoded.split("Basic ")[1]
    user, _ = base64.b64decode(user_encoded).decode("utf-8").split(":")
    url = opa_url + policy_path
    path_as_array = path.split("/")
    token = request.args["token"] if "token" in request.args else None
    j = check_auth(url, user, request.method, request.user_agent.string, request.remote_addr, path_as_array, token).get("result", {})
    if j.get("allow", False) == True:
        return "Success: user %s is authorized \n" % user
    return "Error: user %s is not authorized to %s url /%s \n" % (user, request.method, path)

if __name__ == "__main__":
    app.run()

The function 'check_auth' is responsible to retreive the decision from OPA engine, providing the input details required for authorization. Run the above python script with below command. It uses python modules 'flask' and 'request'.

python echo_server.py
Now we can try to call this API served by this python server and see the authorization policy in action.
curl --user alice:password localhost:5000/finance/salary/alice
Above is allowed based on the 1st rule, user trying to read own salary.
curl --user bob:password localhost:5000/finance/salary/alice
Above is allowed based on the 2nd rule, user trying to read the salary of a subordinate.
curl -X POST -d "empoyeeID=100&value=2000" --user bob:password localhost:5000/finance/salary/alice
This will be allowed based on the 3rd rule, if the user agent also matches the exact same cURL client version we have defined in the policy.
curl -X POST -d "empoyeeID=100&value=2000" --user bob:password localhost:5000/finance/salary/alice
 Even though the previous request was allowed for bob to edit alice's salary, the above request is failed as a user cannot modify own salary based on the defined rule.

Comments

  1. This comment has been removed by a blog administrator.

    ReplyDelete
  2. This comment has been removed by a blog administrator.

    ReplyDelete
  3. This comment has been removed by a blog administrator.

    ReplyDelete
  4. This comment has been removed by a blog administrator.

    ReplyDelete
  5. This comment has been removed by a blog administrator.

    ReplyDelete
  6. This comment has been removed by a blog administrator.

    ReplyDelete
  7. This comment has been removed by a blog administrator.

    ReplyDelete
  8. This comment has been removed by a blog administrator.

    ReplyDelete
  9. This comment has been removed by a blog administrator.

    ReplyDelete
  10. That was really helpful. thanks for sharing.

    ReplyDelete
  11. This comment has been removed by the author.

    ReplyDelete
  12. Wow!!! It was really an Informational Article which provide me with much Insightful Information. I would like to first thank the author for such an Insightful Content. If someone here is looking for a Website Designing Company in India, then look no further than Jeewangarg.com as we are the best website designing company in Delhi working in the arena for the last 8 years.
    Best website designing company in India
    website designing company in Delhi NCR
    Google Partner in India

    ReplyDelete
  13. Thanks for posting on mulesoft 4 training OPA for HTTP Authorization it was so heelpful it clearly explained all my queries and doubts thanks for sharing with us..

    ReplyDelete
  14. At Zohno Inc., we are the best identity access management solutions, creating tools to help IT transformation automation! Check out our products now!

    ReplyDelete
  15. I like your post very much. It is very much useful for my research. I hope you to share more info about this. Keep posting mulesoft training
    servicenow online training
    java online training
    Tableau online training
    ETL Certification
    MongoDB Online Training

    ReplyDelete
  16. I think this is one of the most important info for me.And i am glad reading your article. But want to remark on few general things, The site style is good , the articles is really excellent and also check Our Profile for mule 4 training and mulesoft training online.

    ReplyDelete

Post a Comment

Popular posts from this blog

Signing SOAP Messages - Generation of Enveloped XML Signatures

How to Write a Custom User Store Manager - WSO2 Identity Server 4.5.0