c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith/**
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith *
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * Copyright (c) 2016 ForgeRock AS. All Rights Reserved
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith *
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * The contents of this file are subject to the terms
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * of the Common Development and Distribution License
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * (the License). You may not use this file except in
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * compliance with the License.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith *
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * You can obtain a copy of the License at legal/CDDLv1.0.txt.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * See the License for the specific language governing
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * permission and limitations under the License.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith *
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * When distributing Covered Code, include this CDDL
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * Header Notice in each file and include the License file at legal/CDDLv1.0.txt.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * If applicable, add the following below the CDDL Header,
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * with the fields enclosed by brackets [] replaced by
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * your own identifying information:
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * "Portions Copyrighted [year] [name of copyright owner]"
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith *
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith */
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithpackage com.forgerock.openam.functionaltest.sts.frmwk.rest;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport com.fasterxml.jackson.core.JsonParser;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport com.fasterxml.jackson.databind.ObjectMapper;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport com.forgerock.openam.functionaltest.sts.frmwk.common.CommonConstants;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.json.JsonException;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.json.JsonValue;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.shared.sts.SharedSTSConstants;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.sts.AMSTSConstants;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport com.forgerock.openam.functionaltest.sts.frmwk.common.BasicOpenAMAuthenticator;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.sts.rest.config.user.RestSTSInstanceConfig;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.sts.token.UrlConstituentCatenator;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.sts.token.UrlConstituentCatenatorImpl;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.utils.IOUtils;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.utils.JsonValueBuilder;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport com.forgerock.openam.functionaltest.sts.frmwk.common.STSPublishContext;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport javax.inject.Inject;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport javax.inject.Named;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport java.io.IOException;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport java.io.InputStream;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport java.io.OutputStreamWriter;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport java.net.HttpURLConnection;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport java.net.MalformedURLException;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport java.net.URL;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport java.util.ArrayList;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport java.util.List;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport java.util.logging.Level;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport java.util.logging.Logger;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport static org.forgerock.json.JsonValue.field;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport static org.forgerock.json.JsonValue.json;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport static org.forgerock.json.JsonValue.object;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith/**
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * This class provides an example of how to programatically publish rest-sts instances. It does not provide an
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * exhaustive enumeration of configuration options, but rather provides an indication of how to consume the various
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * classes used to build the configuration state corresponding to a published rest-sts instance.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith */
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithpublic class RestSTSInstancePublisher {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private static final String REST_STS_PUBLISH_SERVICE_VERSION = "protocol=1.0, resource=1.0";
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private static final String COOKIE = "Cookie";
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private static final String EQUALS = "=";
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private static final String ID = "_id";
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private static final String REV = "_rev";
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private final String publishEndpoint;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private final String adminPassword;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private final BasicOpenAMAuthenticator basicOpenAMAuthenticator;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private final RestSTSInstanceConfigFactory restSTSInstanceConfigFactory;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private final UrlConstituentCatenator urlConstituentCatenator;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private final Logger logger;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith /**
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith *
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @param publishEndpoint The url of the publish service: e.g http://myhost.com:8080/openam/rest-sts-publish/publish
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @param adminPassword The amadmin passwordRequired
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * as only admins can consume the rest-sts publish service.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith *
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith */
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith @Inject
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith public RestSTSInstancePublisher(@Named(RestSTSFunctionalTestAPIModule.PUBLISH_ENDPOINT) String publishEndpoint,
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith @Named(CommonConstants.ADMIN_PASSWORD) String adminPassword,
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith BasicOpenAMAuthenticator basicOpenAMAuthenticator,
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith RestSTSInstanceConfigFactory restSTSInstanceConfigFactory,
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith UrlConstituentCatenator urlConstituentCatenator,
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith Logger logger) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith this.publishEndpoint = publishEndpoint;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith this.adminPassword = adminPassword;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith this.basicOpenAMAuthenticator = basicOpenAMAuthenticator;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith this.restSTSInstanceConfigFactory = restSTSInstanceConfigFactory;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith this.urlConstituentCatenator = urlConstituentCatenator;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith this.logger = logger;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith /**
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith An example of the json posted as part of this method invocation:
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith { "invocation_context": "invocation_context_client_sdk", "instance_state": { "oidc-id-token-config": { "oidc-issuer": "oidc_issuer", "oidc-public-key-reference-type": "NONE", "oidc-token-lifetime-seconds": "600", "oidc-authorized-party": null, "oidc-audience": [ "oidc_audience" ], "oidc-signature-algorithm": "HS256", "oidc-claim-map": { "email": "mail" }, "oidc-custom-claim-mapper-class": null, "oidc-custom-authn-context-mapper-class": null, "oidc-custom-authn-method-references-mapper-class": null, "oidc-keystore-location": null, "oidc-keystore-password": null, "oidc-client-secret": "bobo", "oidc-signature-key-alias": null, "oidc-signature-key-password": null }, "supported-token-transforms": [ { "inputTokenType": "X509", "outputTokenType": "OPENIDCONNECT", "invalidateInterimOpenAMSession": true }, { "inputTokenType": "OPENIDCONNECT", "outputTokenType": "SAML2", "invalidateInterimOpenAMSession": true }, { "inputTokenType": "OPENIDCONNECT", "outputTokenType": "OPENIDCONNECT", "invalidateInterimOpenAMSession": true }, { "inputTokenType": "USERNAME", "outputTokenType": "OPENIDCONNECT", "invalidateInterimOpenAMSession": true }, { "inputTokenType": "USERNAME", "outputTokenType": "SAML2", "invalidateInterimOpenAMSession": true }, { "inputTokenType": "OPENAM", "outputTokenType": "SAML2", "invalidateInterimOpenAMSession": false }, { "inputTokenType": "X509", "outputTokenType": "SAML2", "invalidateInterimOpenAMSession": true }, { "inputTokenType": "OPENAM", "outputTokenType": "OPENIDCONNECT", "invalidateInterimOpenAMSession": false } ], "persist-issued-tokens-in-cts": "true", "saml2-config": { "issuer-name": "http://idp.com:8080/openam", "saml2-name-id-format": "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent", "saml2-token-lifetime-seconds": "600", "saml2-custom-conditions-provider-class-name": null, "saml2-custom-subject-provider-class-name": null, "saml2-custom-attribute-statements-provider-class-name": null, "saml2-custom-attribute-mapper-class-name": null, "saml2-custom-authn-context-mapper-class-name": null, "saml2-custom-authentication-statements-provider-class-name": null, "saml2-custom-authz-decision-statements-provider-class-name": null, "saml2-sign-assertion": "true", "saml2-encrypt-assertion": "false", "saml2-encrypt-attributes": "false", "saml2-encrypt-nameid": "false", "saml2-encryption-algorithm": "http://www.w3.org/2001/04/xmlenc#aes128-cbc", "saml2-encryption-algorithm-strength": "128", "saml2-attribute-map": { "email": "mail" }, "saml2-keystore-filename": "/Users/DirkHogan/openam/openam/keystore.jks", "saml2-keystore-password": "changeit", "saml2-sp-acs-url": "http://sp.com:8080/openam/acs", "saml2-sp-entity-id": "http://sp.com:8080/openam", "saml2-signature-key-alias": "test", "saml2-signature-key-password": "changeit", "saml2-encryption-key-alias": "test" }, "deployment-config": { "deployment-url-element": "rest_sts_instance1049252330", "deployment-realm": "/subrealm2021890344", "deployment-auth-target-mappings": { "X509": { "mapping-auth-index-type": "module", "mapping-auth-index-value": "cert_module", "mapping-context": { "x509_token_auth_target_header_key": "client_cert" } }, "OPENIDCONNECT": { "mapping-auth-index-type": "module", "mapping-auth-index-value": "oidc_module", "mapping-context": { "oidc_id_token_auth_target_header_key": "oidc_id_token" } }, "USERNAME": { "mapping-auth-index-type": "service", "mapping-auth-index-value": "ldapService" } }, "deployment-offloaded-two-way-tls-header-key": "also_client_cert", "deployment-tls-offload-engine-hosts": [ "10.0.0.6", "127.0.0.1" ] } } }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith */
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith public String publishInstance(final String urlElement, String realm, STSPublishContext publishContext,
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith CustomTokenOperationContext customTokenOperationContext) throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith RestSTSInstanceConfig instanceConfig =
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith restSTSInstanceConfigFactory.createRestSTSInstanceConfig(urlElement, realm, publishContext, customTokenOperationContext);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith String jsonString = buildPublishInvocationJsonValue(instanceConfig).toString();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith logger.log(Level.SEVERE, "Publishing instance according to the following config state: " + jsonString);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith String response = invokeRestSTSInstancePublish(jsonString);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith logger.log(Level.SEVERE, "Publish result: " + response);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return parseInstanceUrl(response);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith /*
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith The fullSTSId should be the string returned by publishInstance.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith */
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith public String removeInstance(final String fullSTSId) throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith final String result = invokeRestSTSInstanceDeletion(getPublishRemoveInstanceUri(fullSTSId));
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith logger.log(Level.FINE, "Removed rest sts instance: " + fullSTSId);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return result;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith public String updateInstance(final String fullSTSId, RestSTSInstanceConfig restSTSInstanceConfig) throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith final String result = invokeRestSTSInstanceUpdate(getPublishUpdateInstanceUri(fullSTSId),
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith buildPublishInvocationJsonValue(restSTSInstanceConfig).toString());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith logger.log(Level.FINE, "Updated rest sts instance " + fullSTSId);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return result;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith public RestSTSInstanceConfig getPublishedInstance(String stsId) throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith final String response = getPublishedRestSTSInstancesConfigContent(
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith urlConstituentCatenator.catenateUrlConstituents(publishEndpoint, stsId));
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith final List<RestSTSInstanceConfig> configs = parsePublishResponse(response);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith if (configs.isEmpty()) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throw new IOException("No published rest sts instance corresponding to id " + stsId);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith } else if (configs.size() > 1) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throw new IOException("More than a single rest sts instance corresponding to id " + stsId);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith } else {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return configs.get(0);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith public List<RestSTSInstanceConfig> getPublishedInstances() throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith final String response = getPublishedRestSTSInstancesConfigContent(publishEndpoint);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return parsePublishResponse(response);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private List<RestSTSInstanceConfig> parsePublishResponse(String response) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith List<RestSTSInstanceConfig> instanceConfigs = new ArrayList<>();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith JsonValue json;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith try {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith json = JsonValueBuilder.toJsonValue(response);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith } catch (JsonException e) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith logger.log(Level.FINE, "JsonException parsing response: " + response + "\n Exception: " + e);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throw e;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith for (String key : json.asMap().keySet()) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith if (REV.equals(key) || ID.equals(key)) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith continue;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith final JsonValue value = json.get(key);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith RestSTSInstanceConfig instanceConfig = RestSTSInstanceConfig.fromJson(value);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith instanceConfigs.add(instanceConfig);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return instanceConfigs;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private String getPublishedRestSTSInstancesConfigContent(String publishEndpoint) throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith HttpURLConnection connection = (HttpURLConnection)new URL(publishEndpoint).openConnection();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setRequestMethod("GET");
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setRequestProperty(COOKIE, getAdminSessionTokenCookie());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.connect();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return readInputStream(connection.getInputStream());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private String invokeRestSTSInstancePublish(String invocationPayload) throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith HttpURLConnection connection = (HttpURLConnection)getPublishAddInstanceUri().openConnection();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setDoOutput(true);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setRequestMethod("POST");
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setRequestProperty(SharedSTSConstants.CONTENT_TYPE, SharedSTSConstants.APPLICATION_JSON);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setRequestProperty(COOKIE, getAdminSessionTokenCookie());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith writer.write(invocationPayload);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith writer.close();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith if (connection.getResponseCode() == HttpURLConnection.HTTP_CREATED) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return getSuccessMessage(connection);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith } else {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throw new IOException("Could not publish sts instance with content: " + invocationPayload + ": " +
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith getErrorMessage(connection));
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private String invokeRestSTSInstanceDeletion(String deletionUrl) throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith HttpURLConnection connection = (HttpURLConnection)new URL(deletionUrl).openConnection();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setDoOutput(true);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setRequestMethod("DELETE");
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setRequestProperty(SharedSTSConstants.CONTENT_TYPE, SharedSTSConstants.APPLICATION_JSON);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setRequestProperty(COOKIE, getAdminSessionTokenCookie());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.connect();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return getSuccessMessage(connection);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith } else {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throw new IOException("Failed to perform DELETE on url: " + deletionUrl + ": " + getErrorMessage(connection));
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private String invokeRestSTSInstanceUpdate(String updateUrl, String invocationPayload) throws IOException{
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith HttpURLConnection connection = (HttpURLConnection)new URL(updateUrl).openConnection();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setDoOutput(true);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setRequestMethod("PUT");
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setRequestProperty(SharedSTSConstants.CONTENT_TYPE, SharedSTSConstants.APPLICATION_JSON);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith /*
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith Don't remove this version specification - it is necessary to avoid 'upsert' semantics on a PUT. See
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith https://bugster.forgerock.org/jira/browse/CREST-100
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith for details.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith */
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setRequestProperty(SharedSTSConstants.CREST_VERSION_HEADER_KEY, REST_STS_PUBLISH_SERVICE_VERSION);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setRequestProperty(COOKIE, getAdminSessionTokenCookie());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith writer.write(invocationPayload);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith writer.close();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return getSuccessMessage(connection);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith } else {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throw new IOException("Failed to perform PUT on url: " + updateUrl + ": " + getErrorMessage(connection) +
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith ". The connection request method: " + connection.getRequestMethod());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private String getSuccessMessage(HttpURLConnection connection) throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return readInputStream(connection.getInputStream());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private String getErrorMessage(HttpURLConnection connection) throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith if (connection.getErrorStream() != null) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return readInputStream(connection.getErrorStream());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith } else {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return readInputStream(connection.getInputStream());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private String getAdminSessionTokenCookie() throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return "iPlanetDirectoryPro" + EQUALS + getAdminSession();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private String getAdminSession() throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return basicOpenAMAuthenticator.getAdminSSOTokenString("amadmin", adminPassword);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private String readInputStream(InputStream inputStream) throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith if (inputStream == null) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return "Empty error stream";
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith } else {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return IOUtils.readStream(inputStream);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private String parseInstanceUrl(String publishResponse) throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith Object responseContent;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith try {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith JsonParser parser =
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith new ObjectMapper().getFactory().createParser(publishResponse);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith responseContent = parser.readValueAs(Object.class);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith } catch (IOException e) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throw new IOException("Could not map the response from the PublishService to a json object. The response: "
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith + publishResponse + "; The exception: " + e);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return new JsonValue(responseContent).get("url_element").asString();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private URL getPublishAddInstanceUri() throws MalformedURLException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return new URL(publishEndpoint + RestSTSFunctionalTestAPIModule.CREATE_ACTION);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private String getPublishRemoveInstanceUri(String stsId) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return new UrlConstituentCatenatorImpl().catenateUrlConstituents(publishEndpoint, stsId);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private String getPublishUpdateInstanceUri(String stsId) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return new UrlConstituentCatenatorImpl().catenateUrlConstituents(publishEndpoint, stsId);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private JsonValue buildPublishInvocationJsonValue(RestSTSInstanceConfig instanceConfig) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return json(object(
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith field(AMSTSConstants.STS_PUBLISH_INVOCATION_CONTEXT, AMSTSConstants.STS_PUBLISH_INVOCATION_CONTEXT_CLIENT_SDK),
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith field(AMSTSConstants.STS_PUBLISH_INSTANCE_STATE, instanceConfig.toJson())));
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith}