Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.settings
.classpath
.project
.idea
20 changes: 19 additions & 1 deletion _blog-src/_layouts/post.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,25 @@ <h1 style="color: #666; font-weight: bold" class="post-title section-header">{{
<span style="color: #243446; margin-left: 15px; font-size: 13px"><i class="fa fa-tags"></i> {{ page.categories | array_to_sentence_string }}</span>
</header>

<article class="post-content" style="margin-top: 20px; font-size: 14px; line-height: 20px">

{% if page.newUrl %}
<!-- Old Post -->
<p class="bg-warning"
style="margin-top:15px; padding: 10px;">
Note: A newer revision of this blogpost for <b>apiman 1.2.x</b> can be found <a href="{{ site.url }}{{ site.baseurl }}/{{ page.newUrl }}">here</a>. This version was written for <b>apiman 1.1.x</b>.
</p>
{% endif %}

{% if page.oldUrl %}
<!-- New Post -->
<p class="bg-warning"
style="margin-top:15px; padding: 10px;">
Note: This is a redux of our blogpost for <b>apiman 1.2.x</b>. If you're still using <b>apiman 1.1.x</b>, you can refer to the <a href="{{ site.url }}{{ site.baseurl }}/{{ page.oldUrl }}">older revision</a>.
</p>
{% endif %}

<article class="post-content"
style="margin-top: 20px; font-size: 14px; line-height: 20px">
{{ content }}
</article>

Expand Down
470 changes: 470 additions & 0 deletions _blog-src/_posts/2015-01-09-impatient-new-user-redux.markdown

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions _blog-src/_posts/2015-01-09-impatient-new-user.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ title: "An Impatient New User's Introduction to API Management with JBoss apima
date: 2015-01-09 09:15:00
author: len_dimaggio
categories: introduction overview
newUrl: 2015-01-09-impatient-new-user-redux
---

Software application development models are evolutionary things. New technologies are always being created
Expand Down
191 changes: 191 additions & 0 deletions _blog-src/_posts/2015-03-06-custom-policies-redux.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
---
layout: post
title: "Customizing JBoss apiman Through Policy Plugins"
date: 2015-03-06 10:22:00
author: len_dimaggio
categories: plugins policies development maven
oldUrl: 2015-03-06-custom-policies
---

This is the second in a series of articles exploring API management with JBoss apiman. The first article
was a general introduction to apiman for impatient users where in only 10 minutes we installed apiman,
created users and organizations, and APIs, policies, contracts, and client apps. In this article,
we'll take the first step toward customizing apiman by creating new plugins to implement API policies.

<!--more-->

The major new feature added to release 1.0.2 of apiman [http://www.apiman.io/](http://www.apiman.io/) is the ability to extend its features through a custom plugin framework. Since policies perform the most important apiman runtime operations, plugins that enable you to create new policies are the first type of plugins to be supported.

In this article, we'll examine all the steps that you must perform to create a new policy plugin, and then import it into apiman and configure an API to put it into use.

## Prerequisites

For this article, we'll assume that you have completed all the steps in the first article in this series. The first article guides even the most impatient user through installing and using apiman.

## Accessing the Example Plugins

Like all JBoss software, apiman provides functioning example code that you can use as a starting point for your own plugins. The easiest way to create and package an apiman is as a standard maven project packaged as a .war file.

To download a copy of the example plugins, execute this git command:

git clone https://github.com/apiman/apiman-plugins

When the git clone operation completes, you'll have the source code for multiple example plugins. The exact set of plugins that you have downloaded may change, depending on when you download them, as more examples are always being added. For the purposes of this article, we'll focus on the "config-policy" example plugin. This plugin demonstrates how a plugin can be used to set the value of properties in a message being processed by an API. Specifically, this plugin defines properties in the request and response headers and enables you to set their values to "true."

## Requirements for a Plugin Implementation

The easiest way that an apiman policy plugin can be build and packaged is as a standard maven project packaged as a .war file. There are just a few modifications that are required to convert a .war into a plugin.

Let's take a closer look at the files and directories that comprise the apiman config-policy plugin, and the changes that are needed to implement a plugin:

├---pom.xml
└---src
└---main
├---apiman
│ ├---plugin.json
│ └---policyDefs
│ ├---config-policyDef.json
│ └---schemas
│ └---config-policyDef.schema
└---java
└---io
└---apiman
└---plugins
└---config_policy
├---ConfigBean.java
└---ConfigPolicy.java

The most obvious difference is the addition of the "apiman" directory. This directory is used to contain the configuration files for the plugin. (In other words, the files that make the project a plugin.) The only project-wide configuration change that you have to make is to modify the plugin's maven pom.xml file to include the apiman directory when the project is built. The following lines are added to the plugin's pom.xml file:

{% highlight xml %}
<resource>
<directory>src/main/apiman</directory>
<targetPath>META-INF/apiman</targetPath>
<filtering>true</filtering>
</resource>
{% endhighlight %}

The result of these statements in the pom.xml file is that the contents of the apiman directory are included in the project build's META-INF directory. (We'll take a look at this later when we build the plugin project.) Setting filtering to true enables maven property expansion during the creation of the plugin war file.
Configuration files for the plugin are contained in the apiman directory. The primary configuration file is the "plugin.json" file. This file is required for all apiman plugins, regardless of the plugin type. The meta-data contained in this file describes the plugin and is displayed in the API Manager UI.

Since our example is contributing a policy, it must contain a JSON file that defines the policy. This JSON file is contained in the apiman/policyDefs directory and is named "config-policyDef.json." This file defines the following fields for the policy:

* *id* - A unique identifier for the policy
* *name* - A user friendly (in other words, a human readable) name for the policy. This policy name is displayed in the API Manager UI
* *description* - A description of the policy
* *policyImpl* - This is the fully qualified classname name of the Java class that actually implements the policy. This value must be properly formatted to include information about the plugin, including placeholders for maven properties, for example, project version.
* *icon* - This is the name of a Font Awesome icon [http://fortawesome.github.io/Font-Awesome/](http://fontawesome.github.io/Font-Awesome/) that is displayed for the Policy in the API Manager UI.
* *formType* - The type of policy configuration UI form. Our example uses JsonSchema.
* *form* - This is a relative path to the policy configuration UI form contained in the plugin. Our examples uses the JSON Schema that defines the configuration data format. (More on this file in a minute.

In our example, the config-policyDef.json looks like this:

{% highlight json %}
{
"id" : "config-policy",
"name" : "Config Policy",
"description" : "A policy used to showcase policy configuration.",
"policyImpl" "plugin:${project.groupId}:${project.artifactId}:${project.version}:${project.packaging}/io.apiman.plugins.config_policy.ConfigPolicy",
"icon" : "sliders",
"formType" : "JsonSchema",
"form" : "schemas/config-policyDef.schema"
}
{% endhighlight %}

We mentioned that since our example uses the JSON schema [http://json-schema.org/documentation.html](http://json-schema.org/documentation.html), we have to also define the configuration data format. This is done in the policyDefs/schemas/config-policyDef.schema file. This file defines the format used in the policy configuration file data and is used by the API Manager UI to generate a form that is used to fill in the values to be used to configure the policy. In our example, the policy's JSON schema defines two properties: requestHeader and responseHeader.

{% highlight json %}
{
"title" : "Configure HTTP Headers",
"description" : "Set the HTTP request header to populate with the value 'true' when the request is made. Also set the HTTP response header to populate with the value 'true' after the response is received from the back-end API.",
"type" : "object",
"properties": {
"requestHeader": {
"title" : "Request Header",
"type" : "string",
"minLength" : 1,
"maxLength" : 64
},
"responseHeader": {
"title" : "Response Header",
"type" : "string",
"minLength" : 1,
"maxLength" : 64
}
}
}
{% endhighlight %}

That finishes the description of the policy's configuration files. To complete the policy plugin, the example also requires the Java implementation for the policy itself. The policy implementation is contained in the src/main/java/io/apiman/plugins/config_policy/ConfigPolicy.java file. The policy is very simple as it merely appends a header to the http request and response.

Java policy classes must implement the apiman IPolicy interface. This example takes that a step further by actually extending the io.apiman.gateway.engine.policies.AbstractMappedPolicy class. By doing so, the policy Java code can take advantage of the AbstractMappedPolicy's class use of the Jackson (https://github.com/FasterXML/jackson) JSON parser to parse the policy configuration data into a Java bean. (In this example, the bean is implemented in src/main/java/io/apiman/plugins/config_policy/ConfigBean.java.) If the policy implemented the IPolicy interface, instead of extending AbstractMappedPolicy, then the policy Java class would have to implement its own parser.

## Building the Plugin and Installing it into the Maven Repo

Building the plugin with maven is easy. Just execute this command from the directory that contains the plugin's pom.xml file.

mvn install

In case you're wondering why, we're installing the plugin into the maven repo. The answer is simply that in the current release of apiman, the only supported install path is from the maven repo. Future releases of apiman will likely support additional installation paths.

## Installing a Plugin into apiman

In apiman, a policy plugin, once installed, is available on a system-wide basis. Accordingly, plugins can only be installed by an admin user. After you login as admin, you'll see this in the admin UI:

![System Administration](/blog/images/2015-03-06/apiman-1.png)

After selecting "Manage Plugins," you'll see a screen that looks like this:

![Plugins](/blog/images/2015-03-06/apiman-2.png)

And, if you then select "Add Plugin," you'll see this screen:

![Add Plugin](/blog/images/2015-03-06/apiman-3.png)

The GroupId, ArtifactId, and Version information is all available in the example plugin's pom.xml file:

* *GroupId*: io.apiman.plugins
* *ArtifactId*: apiman-plugins-config-policy
* *Version*: 1.0.3-SNAPSHOT

After you enter this information for the plugin and click on "Add Plugin," you'll see this displayed in the UI:

![Plugins](/blog/images/2015-03-06/apiman-4.png)

Congratulations! The plugin is installed and is ready to be used! Let's add it to an API and see it in action.

## Using the Installed Plugin

First, we have to log out of the admin account in the Admin UI and then log back in as the "serprov" API provider. Then, select our "echo" API, and create a new version of the API, based on the original version of the API:

![New API Version](/blog/images/2015-03-06/apiman-6.png)

And, when you add a new policy to the API, you'll see the example config API that we just installed:

![Add Policy](/blog/images/2015-03-06/apiman-5.png)

When you select the Config Policy, you'll be presented with a dialog where you can specify the values for the two properties defined in the policy:

![Add Policy](/blog/images/2015-03-06/apiman-7.png)

Let's fill in some easy to remember values:

![Add Policy](/blog/images/2015-03-06/apiman-8.png)

After adding the policy, you'll see it displayed in the policies defined for the API:

![Add Policy](/blog/images/2015-03-06/apiman-9.png)

Then publish the API. In order to consume the API, login to the API Manager UI as the client app developer "appdev", and create a new client app that uses the new API. (We covered the creation of new client apps in detail in the first article in this series)

And when the API is invoked, you'll see something like this:

![REST Client](/blog/images/2015-03-06/apiman99.png)

And this:

![REST Client](/blog/images/2015-03-06/apiman100.png)

## In Conclusion

OK, let's recap. apiman is a rapidly growing and developing project. Each new release brings new features. In release 1.0.2, it became possible for users to contribute custom policies into their apiman installation through the API Manager UI.
1 change: 1 addition & 0 deletions _blog-src/_posts/2015-03-06-custom-policies.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ title: "Customizing JBoss apiman Through Policy Plugins"
date: 2015-03-06 10:22:00
author: len_dimaggio
categories: plugins policies development maven
newUrl: 2015-03-06-custom-policies-redux
---

This is the second in a series of articles exploring API management with JBoss apiman. The first article
Expand Down
66 changes: 66 additions & 0 deletions _blog-src/_posts/2015-05-08-authorization-redux.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
layout: post
title: "Authorization: good god, what is it good for?"
date: 2015-05-08 13:15:15
author: eric_wittmann
categories: authorization authentication policy
oldUrl: 2015-05-08-authorization
---

Quite a bit, actually. :)

I want to talk about how Authorization currently works in apiman, because it's
a little bit more loosely coupled than you might expect. Note that at some
point in the future we're going to be renovating how policies are defined and
configured in the API Manager UI. But until then, you can refer to this blog
post for an overview of how to configure Authorization!

<!--more-->

I won't bury the lead - the key to getting Authorization to work is understanding
that it *only* works together with Authentication. First you must add and
configure a compatible *Authentication* policy, which will be responsible for
extracting the user's roles and passing them along to the Authorization policy.

## Define your terms, sir!
Let's make sure we're on the same page with respect to terminology, shall we?

* **Authentication**: the act of validating that a user is who she claims to be, by checking provided credentials against some source of identity. Examples include BASIC Authentication and OAuth2.
* **Authorization**: the act of ensuring that the authenticated user has *permission* to perform the requested action or view the requested data. Typically involves checking that the user possesses one or more required roles.

## How does this work in apiman?

I'm glad you asked. In apiman we have split these two functions out into separate policies. This allows us to use the same Authorization policy regardless of what type of Authentication is being used.

Basically you need to do the following two things:

1. Add and configure an Authentication policy such as the BASIC Authentication Policy or the Keycloak OAuth2 Authentication Policy
1. Add and configure an Authorization Policy.

That's it in a nutshell!

## Give me more details!

OK, OK. If you're reading this you probably know the apiman basics - how to create Organizations and APIs and whatnot. If not, I would recommend you check out the [User Guide](http://www.apiman.io/latest/user-guide.html) or the [Tutorials](http://www.apiman.io/latest/tutorials.html).

Once you have an API that you want to configure, go ahead and add a new policy. Choose, for example, the *BASIC Authentication Policy* and configure it as seen in the following screenshot:

![Example BASIC Authentication configuration](/blog/images/2015-05-08/basic-auth-config.png)

Once you've added that policy, you can add the Authorization Policy - make sure they are in the proper order, since the Authentication policy must execute first. Configure the Authorization Policy however you like, using roles appropriate for your users. For example, it might look like this:

![Example Authorization configuration](/blog/images/2015-05-08/authorization-config.png)

Once all is said and done, you should have two (at least) policies configured for your API. It might look something like this in the UI:

![Example policy list](/blog/images/2015-05-08/auth-policies.png)

If you follow those steps, everything should work out alright for you! The Authorization Policy is capable of being quite fine-grained. You can configure role based access via custom resource location regular expressions and HTTP verb(s). If all you want is a global required role to access your API, that's easy too:

* **Resource Path**: /.*
* **Verb/action**: *
* **Required Role**: <your-role>

Good luck and come find us on the mailing list or IRC if you have any trouble!

/post
2 changes: 2 additions & 0 deletions _blog-src/_posts/2015-05-08-authorization.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ title: "Authorization: good god, what is it good for?"
date: 2015-05-08 13:15:15
author: eric_wittmann
categories: authorization authentication policy
newUrl: 2015-05-08-authorization-redux
---

Quite a bit, actually. :)

I want to talk about how Authorization currently works in apiman, because it's
Expand Down
Loading