Tuesday, February 25, 2014

OAM 11g PS2 Rest API Characteristics - Deleting Host Identifiers

This is a short post to capture some useful characteristics of the API when deleting a Host Identifier. Specifically, what if the delete is successful versus what if that Host Identifier can't be found? Using the same setup as before I delete a non-existent Identifier and then one that I know exists having just created it. The traffic for both is captured below:

Host Identifier Not Found

When the host identifier being specified isn't found, the traffic pattern looks like as follows within the WAMulator. I've included two such request and response cycles; one for deleting by name and the other for deleting by id.

Not Found By Name

Elapsed Time (ms): 5360
REQUEST Bytes to SERVER: 473

Canonical Req. Line: DELETE /oam/services/rest/11.1.2.0.0/ssa/policyadmin/hostidentifier?name=aab4a168731a342a497ce32e013a3ce34 HTTP/1.1
Rewritten Req. Line: DELETE /oam/services/rest/11.1.2.0.0/ssa/policyadmin/hostidentifier?name=aab4a168731a342a497ce32e013a3ce34 HTTP/1.1
Accept: application/json
User-Agent: Java/1.6.0_65
Host: localhost.lds.org:8080
Connection: close
X-Wmltr: handled
X-Forwarded-Scheme: http
cctx: /{/.../*,*}


RESPONSE Bytes to CLIENT: 442
HTTP/1.1 200 OK
Date: Fri, 21 Feb 2014 16:04:20 GMT
Transfer-Encoding: chunked
Content-Type: text/plain
Set-Cookie: JSESSIONID=lSpGTH5G1NS70RbyTnmsM6g4yd2BLM0ksMNG5RwJ85NGpynDMLvQ!-955026361; path=/; HttpOnly
x-oracle-dms-ecid: 32bcdd031430eb16:7e79f4e9:144504ffa11:-8000-000000000001e313
x-powered-by: Servlet/2.5 JSP/2.1
Connection: close
X-ConnId: C-012

003a
HostIdentifier not found:aab4a168731a342a497ce32e013a3ce34
0000


Not Found by Id

Elapsed Time (ms): 51
REQUEST Bytes to SERVER: 466

Canonical Req. Line: DELETE /oam/services/rest/11.1.2.0.0/ssa/policyadmin/hostidentifier?id=non-existent-host-identifier HTTP/1.1
Rewritten Req. Line: DELETE /oam/services/rest/11.1.2.0.0/ssa/policyadmin/hostidentifier?id=non-existent-host-identifier HTTP/1.1
Accept: application/json
Authorization: Basic d2VibG9naWM6b2FtMTFncjI=
User-Agent: Java/1.6.0_65
Host: localhost.lds.org:8080
Connection: close
X-Wmltr: handled
X-Forwarded-Scheme: http
cctx: /{/.../*,*}

RESPONSE Bytes to CLIENT: 437
HTTP/1.1 200 OK
Date: Tue, 25 Feb 2014 17:12:42 GMT
Transfer-Encoding: chunked
Content-Type: text/plain
Set-Cookie: JSESSIONID=3GTnTMPKYwGhmf8xDzFDg1y92BLZwCcs5fqGKRQ4cJmnK1Jxn2Jv!834987041; path=/; HttpOnly
x-oracle-dms-ecid: 32bcdd031430eb16:-4432c526:14465107ab6:-8000-0000000000014c0c
x-powered-by: Servlet/2.5 JSP/2.1
Connection: close
X-ConnId: C-021

0035
HostIdentifier not found:non-existent-host-identifier
0000

Host Identifier Found and Deleted

In contrast the following request and response cycles portray successfully finding and deleting a host identifier. Again, I've include deleting by name and deleting by id.

Delete by ID

Elapsed Time (ms): 61228
REQUEST Bytes to SERVER: 471

Canonical Req. Line: DELETE /oam/services/rest/11.1.2.0.0/ssa/policyadmin/hostidentifier?id=ac8576f6258644a9388f5e692400bca25 HTTP/1.1
Rewritten Req. Line: DELETE /oam/services/rest/11.1.2.0.0/ssa/policyadmin/hostidentifier?id=ac8576f6258644a9388f5e692400bca25 HTTP/1.1
Accept: application/json
User-Agent: Java/1.6.0_65
Host: localhost.lds.org:8080
Connection: close
X-Wmltr: handled
X-Forwarded-Scheme: http
cctx: /{/.../*,*}



RESPONSE Bytes to CLIENT: 443
HTTP/1.1 200 OK
Date: Fri, 21 Feb 2014 16:14:11 GMT
Transfer-Encoding: chunked
Content-Type: text/plain
Set-Cookie: JSESSIONID=C2KJTH7TvFnL9bHtnSN1nStbW2cH1Tz1FRY2pJcnQdJQxrWKZYqf!-955026361; path=/; HttpOnly
x-oracle-dms-ecid: 32bcdd031430eb16:7e79f4e9:144504ffa11:-8000-000000000001e6e0
x-powered-by: Servlet/2.5 JSP/2.1
Connection: close
X-ConnId: C-018

003b
HostIdentifier is deleted:ac8576f6258644a9388f5e692400bca25
0000

Delete by Name

Elapsed Time (ms): 10307
REQUEST Bytes to SERVER: 480

Canonical Req. Line: DELETE /oam/services/rest/11.1.2.0.0/ssa/policyadmin/hostidentifier?name=it--70a5951b-11af-4b68-9f44-593b82152337 HTTP/1.1
Rewritten Req. Line: DELETE /oam/services/rest/11.1.2.0.0/ssa/policyadmin/hostidentifier?name=it--70a5951b-11af-4b68-9f44-593b82152337 HTTP/1.1
Accept: application/json
Authorization: Basic d2VibG9naWM6b2FtMTFncjI=
User-Agent: Java/1.6.0_65
Host: localhost.lds.org:8080
Connection: close
X-Wmltr: handled
X-Forwarded-Scheme: http
cctx: /{/.../*,*}


RESPONSE Bytes to CLIENT: 450
HTTP/1.1 200 OK
Date: Tue, 25 Feb 2014 17:12:31 GMT
Transfer-Encoding: chunked
Content-Type: text/plain
Set-Cookie: JSESSIONID=1GKXTMTfpPyGn0cxpbrTTvYgcypvJTJ4kYJJTLZGL3CFRvvJBvDM!834987041; path=/; HttpOnly
x-oracle-dms-ecid: 32bcdd031430eb16:-4432c526:14465107ab6:-8000-0000000000014c00
x-powered-by: Servlet/2.5 JSP/2.1
Connection: close
X-ConnId: C-020

0042
HostIdentifier is deleted:it--70a5951b-11af-4b68-9f44-593b82152337
0000

Again, 61 seconds and 10 seconds to delete an item are terribly slow and we have been told that times are supposed be improving at some point. Slowness aside, takeaways from these results are that the response payload must be evaluated to determine if the request was a success or not. Namely, if the payload contains "deleted" it was successful. If it contains "not found" then it was unable to delete the item. Although arguably the request was successful. Wasn't it? The desire was for the object to not be accessible and a "not found" result meets that criteria.



Friday, February 21, 2014

OAM 11g PS2 Rest API Characteristics - Host Identifiers

Following on from my last post I wanted to answer the following question: Can I search for a Host Identifier object by its name, id, and associated DNS host names? Host Identifier objects have a name, a unique identifier that looks very much like a GUID, and one or more DNS host names with optional port used to match the Host header in http traffic being protected. Oracle documentation for the API indicates that we can query for a Host Identifier by id and name. The question is, does name include the DNS host names that are embedded?

To answer this question I set up a similar test suite and again ran the tests through the WAMulator to see what the http payload looked like. The test suite code is shown below. Details of the interaction with the REST API are encapsulated within the ohids object (short for the class name OAMHostIdentifierService) which I can share if there is interest. I'm using Spring to auto-wire and inject that service. And I'm using Java's UUID class to create some host names that won't conflict with real values already in our test environment. TestNG is being used as the framework for running these tests and sequencing them using its dependsOnMethods aspect.

Note that I do some validation in all but the two tests where I attempt to get the Host Identifier by the two DNS names embedded in the originally created Host Identifier. I don't know what to expect and I want the tests will to run to completion and, as any test should, clean up any relics of the test so that we are back to the state that we were in before running the tests. Of course if some of the other tests failed I'd have to go clean up the objects manually so it isn't completely rock solid.


private String identifierName 
    = "it--" + UUID.randomUUID().toString();
private String dnsName1 
    = "it--dns-" + UUID.randomUUID().toString();
private String dnsName2 
    = "it--dns-" + UUID.randomUUID().toString();
private String identifierId = null;


@Test
public void createHostIdentifierTwoDnsHosts() {
    List<Host> hosts = new ArrayList<Host>();
    hosts.add(new Host(dnsName1));
    hosts.add(new Host(dnsName2));
    OAMHostIdentifier id 
        = new OAMHostIdentifier( identifierName, hosts);
    String response = ohids.createHostIdentifier(endpoint, id);
    Assert.assertTrue(response.contains("?id="), 
        "successful creation should return URL for accessing new object");
    // cache returned id for use in verifying other tests
    // split around the characters "?id=" in returned URL
    identifierId = response.split("\\?id\\=")[1]; 
}

@Test(dependsOnMethods = "createHostIdentifierTwoDnsHosts")
public void getHostIdentifierByName() {
    OAMHostIdentifier id 
        = ohids.getHostIdentifierByName(endpoint, identifierName, Resources.CACHE.NOT_ALLOWED);
    Assert.assertNotNull(id, "search for host identifier by name should not return null.");
    Assert.assertEquals(id.getId(), identifierId, "search for host identifier by name should return identifier with same ID.");
}

@Test(dependsOnMethods = "getHostIdentifierByName")
public void getHostIdentifierById() {
    OAMHostIdentifier id 
        = ohids.getHostIdentifierById(endpoint, identifierId, Resources.CACHE.NOT_ALLOWED);
    Assert.assertNotNull(id, "search for host identifier by id should not return null.");
    Assert.assertEquals(id.getId(), id.getId(), "search for host identifier by id should return identifier with same ID.");
}

@Test(dependsOnMethods = "getHostIdentifierById")
public void getHostIdentifierByDnsHost1() {
    OAMHostIdentifier id 
        = ohids.getHostIdentifierByName(endpoint, dnsName1, Resources.CACHE.NOT_ALLOWED);
    System.out.println((id == null ? "Host Identifier NOT found by DNS-1 name" : "Host Identifier found by DNS-1 name"));
}

@Test(dependsOnMethods = "getHostIdentifierByDnsHost1")
public void getHostIdentifierByDnsHost2() {
    OAMHostIdentifier id 
        = ohids.getHostIdentifierByName(endpoint, dnsName2, Resources.CACHE.NOT_ALLOWED);
    System.out.println((id == null ? "Host Identifier NOT found by DNS-2 name" : "Host Identifier found by DNS-2 name"));
}

@Test(dependsOnMethods = "getHostIdentifierByDnsHost2")
public void deleteHostIdentifierById() {
    String msg = ohids.deleteHostIdentifierById(endpoint, identifierId);
    Assert.assertNotNull(msg, "delete host identifier should not return null.");
    Assert.assertTrue(msg.contains("HostIdentifier is deleted"), "delete host identifier response should contain the text, 'HostIdentifier is deleted'.");
}

The tests run successfully to completion. However, when I look at the console output for each test I note that the requests for the Host Identifier by DNS name both show the answer I was seeking: 

Host Identifier NOT found by DNS-1 name
Host Identifier NOT found by DNS-2 name

And when looking at the http traffic as it passes through the WAMulator for getting the Host Identifier by name or Id I see the following payload being returned:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><HostIdentifiers>
<HostIdentifier>
    <id>a4458dae484b04246bcea4c1804b9b9c4</id>
    <name>it--74705474-6703-4d6d-adea-6595d72c2682</name>
    <Hosts>
        <host>
            <hostName>it--dns-0a5d6dcc-2a83-4121-8fdf-d822351016e6</hostName>
        </host>
        <host>
            <hostName>it--dns-02bf280f-4cb9-482f-bdfe-e7369023d573</hostName>
        </host>
    </Hosts>
</HostIdentifier>
</HostIdentifiers>

But for the queries by DNS names the result including request and response headers is as follows. Note that the request gives an http 200 response but the list of HostIdentifiers in this case is empty:

Canonical Req. Line: GET /oam/services/rest/11.1.2.0.0/ssa/policyadmin/hostidentifier?name=it--dns-0a5d6dcc-2a83-4121-8fdf-d822351016e6 HTTP/1.1
Rewritten Req. Line: GET /oam/services/rest/11.1.2.0.0/ssa/policyadmin/hostidentifier?name=it--dns-0a5d6dcc-2a83-4121-8fdf-d822351016e6 HTTP/1.1
Accept: application/xml
User-Agent: Java/1.6.0_65
Host: localhost.lds.org:8080
Connection: close
X-Wmltr: handled
X-Forwarded-Scheme: http
cctx: /{/.../*,*}

RESPONSE Bytes to CLIENT: 455
HTTP/1.1 200 OK
Date: Fri, 21 Feb 2014 16:16:50 GMT
Content-Length: 90
Content-Type: application/xml
Set-Cookie: JSESSIONID=4HD2TH7SqPJ29nbKPKLNqBF4RSjsVgvhCbGRB2ShvXLsSTLfyQD1!-955026361; path=/; HttpOnly
x-oracle-dms-ecid: 32bcdd031430eb16:7e79f4e9:144504ffa11:-8000-000000000001e7ee
x-powered-by: Servlet/2.5 JSP/2.1
Connection: close
X-ConnId: C-022

<?xml version="1.0" encoding="UTF-8" standalone="yes"?><HostIdentifiers></HostIdentifiers>

So I've got the answer to my question. You can query OAM for a Host Identifier using its name or its id but not any of the nested DNS names that it represents.

Wednesday, February 19, 2014

OAM 11g PS2 Rest API Characteristics

For those of you attempting to use OAM 11g's Restful API to manage your access policies and wondering about responses for corner cases for creating Host Identifiers, this blog entry is for you.

I've been messing around with Oracle Access Manager's Restful API introduced in their 11g product. At time of posting available documentation was unclear on some behavioral characteristics. So I've captured some of those in this blog. I'm using Apache's HttpClient to generate the HTTP requests routing the traffic through an instance of the WAMulator proxy to capture the content below.

As noted in the title I'm running against 11g PS2. (PS2 means patch set 2 not the game console or the operating system for those old enough to remember it.) Note that the elapsed times are quite slow and Oracle is promising significant improvements by year's end in PS3.

Three responses are captured in this blog: successfully creating a Host Identifier, failure due to a name conflict, and failure due to a DNS host being specified that is already in use by another Host Identifier. Note that some headers have been removed so as not to share information that I don't want to share like the Authorization header. Sorry. Note also that the names and DNS hosts are UUIDs prefixed with the characters "it" which stands for integration test and intentionally do not correlate to real DNS entries.

Successfully Creating a Host Identifier

Creating a new host identifier with a name that does not conflict with an existing host identifier name and has dns hosts that are not already found in an existing host identifier looks like the following when captured by the WAMulator:

 Elapsed Time (ms): 7855
 REQUEST Bytes to SERVER: 762

 Canonical Req. Line: POST /oam/services/rest/11.1.2.0.0/ssa/policyadmin/hostidentifier HTTP/1.1
 Rewritten Req. Line: POST /oam/services/rest/11.1.2.0.0/ssa/policyadmin/hostidentifier HTTP/1.1
 Accept: application/xml
 Content-Type: application/xml
 User-Agent: Java/1.6.0_65
 Host: localhost.lds.org:8080
 Content-Length: 279
 X-Wmltr: handled
 X-Forwarded-Scheme: http

 <?xml version="1.0" ?><HostIdentifier><name>it--2ac02905-ab92-401b-87c5-9d914ce0ce50</name><Hosts><host><hostName>it--dns-da23d9c9-148d-4bc3-b571-1d3ab36385fe</hostName></host><host><hostName>it--dns-405afc94-bdf2-40a2-9552-ebad322b6dbb</hostName></host></Hosts></HostIdentifier>
  
 RESPONSE Bytes to CLIENT: 515
 HTTP/1.1 201 Created
 Date: Wed, 19 Feb 2014 20:56:52 GMT
 Transfer-Encoding: chunked
 Content-Type: text/plain
 Set-Cookie: JSESSIONID=NbJ1TFhJ2p1c9yppQx4mylPRLyGkpQm5k4mcLF1vmvcQtvDZ80dJ!998573338; path=/; HttpOnly
 x-oracle-dms-ecid: 32bcdd031430eb16:-34effd2e:144466504e7:-8000-0000000000014d84
 x-powered-by: Servlet/2.5 JSP/2.1
 Connection: close
 X-ConnId: C-109

 007e 
 http://localhost.lds.org:8080/oam/services/rest/11.1.2.0.0/ssa/policyadmin/hostidentifier?id=a9dcfc7f9f2fe4951bb7286411bd52783
 0000


Failure Due To Duplicate Name


When attempting to create a host identifier with the same name as had by an existing host identifier, namely the one created above, the following response is seen:

 Elapsed Time (ms): 3957
 REQUEST Bytes to SERVER: 684

 Canonical Req. Line: POST /oam/services/rest/11.1.2.0.0/ssa/policyadmin/hostidentifier HTTP/1.1
 Rewritten Req. Line: POST /oam/services/rest/11.1.2.0.0/ssa/policyadmin/hostidentifier HTTP/1.1
 Accept: application/xml
 Content-Type: application/xml
 User-Agent: Java/1.6.0_65
 Host: localhost.lds.org:8080
 Content-Length: 201
 X-Wmltr: handled
 X-Forwarded-Scheme: http

 <?xml version="1.0" ?><HostIdentifier><name>'''it--2ac02905-ab92-401b-87c5-9d914ce0ce50'''</name><Hosts><host><hostName>it--dns-7e612f4f-d8e3-4a65-a5e6-132355049665</hostName></host></Hosts></HostIdentifier>

  
 RESPONSE Bytes to CLIENT: 476
 HTTP/1.1 424 Unknown
 Date: Wed, 19 Feb 2014 20:57:01 GMT
 Transfer-Encoding: chunked
 Content-Type: text/plain
 Set-Cookie: JSESSIONID=kFrBTFhdrp25yMvw2Xw7rQvDy8bxpcGJlWjyWSd34HQ866y6pQlY!998573338; path=/; HttpOnly
 x-oracle-dms-ecid: 32bcdd031430eb16:-34effd2e:144466504e7:-8000-0000000000014d8f
 x-powered-by: Servlet/2.5 JSP/2.1
 Connection: close
 X-ConnId: C-110

 0057
 An object of this type named "it--2ac02905-ab92-401b-87c5-9d914ce0ce50" already exists.
 0000


Failure Due To DNS Host Already In Use


When Creating a new Host Identifier containing a DNS host that is already used in another Host Identifier, namely the one created above, results in the following response:

 Elapsed Time (ms): 4008
 REQUEST Bytes to SERVER: 762

 Canonical Req. Line: POST /oam/services/rest/11.1.2.0.0/ssa/policyadmin/hostidentifier HTTP/
 Rewritten Req. Line: POST /oam/services/rest/11.1.2.0.0/ssa/policyadmin/hostidentifier HTTP/1.1
 Accept: application/xml
 Content-Type: application/xml
 User-Agent: Java/1.6.0_65
 Host: localhost.lds.org:8080
 Content-Length: 279
 X-Wmltr: handled
 X-Forwarded-Scheme: http
 cctx: /{/.../*,*}

 <?xml version="1.0" ?><HostIdentifier><name>it--0bf076e7-c9e2-4275-b57a-ca13de4d52fb</name><Hosts><host><hostName>'''it--dns-da23d9c9-148d-4bc3-b571-1d3ab36385fe'''</hostName></host><host><hostName>it--dns-405afc94-bdf2-40a2-9552-ebad322b6dbb</hostName></host></Hosts></HostIdentifier>


 RESPONSE Bytes to CLIENT: 550
 HTTP/1.1 424 Unknown
 Date: Wed, 19 Feb 2014 20:57:05 GMT
 Transfer-Encoding: chunked
 Content-Type: text/plain
 Set-Cookie: JSESSIONID=P60yTFhBdJLHqjw1QwpssJVTbSwxtpVRpmfwnKlzFgSQdFSThDnm!998573338; path=/; HttpOnly
 x-oracle-dms-ecid: 32bcdd031430eb16:-34effd2e:144466504e7:-8000-0000000000014d96
 x-powered-by: Servlet/2.5 JSP/2.1
 Connection: close
 X-ConnId: C-111

 00a1
 Host "Host hostName:="it--dns-da23d9c9-148d-4bc3-b571-1d3ab36385fe", port=null"" already exists under host identifier "it--2ac02905-ab92-401b-87c5-9d914ce0ce50".
 0000

Yes, that "null" followed by double quotes is how the response comes back. I don't know if Oracle will be fixing that or not. That is it for today. I'll share Tech-To-Do results as they are available. Thanks for reading.