Funktionen entwickeln
Bevor Sie ein API-Gateway-Deployment bereitstellen, müssen Sie Ihre Funktionen entwickeln und bereitstellen.
Informationen zur Geschäftslogik
Der Wichtigkeit der Implementierung besteht darin, einen Code in eine Funktion einzufügen. Dieser Code könnte bei Bedarf komplex sein und mehrere Endpunkte aufrufen oder eine Aggregation durchführen. Die Geschäftslogikfunktion ist der Code, der aufgerufen wird, wenn er von Oracle Cloud Infrastructure API Gateway benötigt wird.
In dieser Beispielarchitektur ruft das API-Gateway eine Oracle-Funktion auf, die wiederum einige Daten von Oracle Fusion Applications Cloud Service über die REST-API abfragt, bearbeitet und an den Benutzer zurückgibt. Beim Schreiben der Funktion selbst können Sie ein beliebiges geeignetes Framework verwenden, müssen jedoch die Auswirkungen eines Frameworks auf serverlose Funktionen kennen. In diesem Beispiel wurden Java als Sprache und die Apache HttpClient-Library verwendet, um eine Verbindung zum REST Service herzustellen. Die Apache-Library wurde ausgewählt, weil sie einfach zu verwenden und einfach zu implementieren war. In Java 11 ist jetzt jedoch der neue HTTP-Client vorhanden, der ebenfalls verwendet werden könnte.
Außerdem sollten Sie Frameworks vermeiden, die zahlreiche In-Memory-Objekte beim Aufruf von REST-APIs instanziieren, da diese Objekte bei jedem Aufruf verworfen werden und somit die Ausführung der Funktion verlangsamen wird.
Informationen zum Abrufen von Benutzernamen und Rollen
Wenn eine Funktion von Oracle Cloud Infrastructure API-Gateway aufgerufen wird, fügt das Gateway einige Metadaten in den Aufruf mit HTTP-Headern ein. Auf diese Header kann mit dem Funktions-SDK zugegriffen werden.
Beispiel: Im folgenden Snippet von Java-Code (aus der Klasse JWTUtils
im mit diesem Lösungsplaybook bereitgestellten Beispielcode) wird das Authentifizierungstoken extrahiert, decodiert und anschließend als Teil des Bodys an den Aufrufer zurückgegeben.
public OutputEvent handleRequest(InputEvent rawInput) {
Optional<string> optionalToken=rawInput.getHeaders().get("Fn-Http-H-Authorization");
if (!optionalToken.isPresent())
{
throw new Exception("No Authentication Bearer token found");
}
String jwtToken=optionalToken.get().substring(TOKEN_BEARER_PREFIX.length());
String[] split_string = jwtToken.split("\\.");
String base64EncodedHeader = split_string[0];
String base64EncodedBody = split_string[1];
String base64EncodedSignature = split_string[2];
byte[] decodedJWT = Base64.getDecoder().decode(base64EncodedBody);
try {
String JSONbody = new String(decodedJWT, "utf-8");
ObjectMapper mapper = new ObjectMapper();
JsonNode root=mapper.readTree(JSONbody);
username=root.get("sub").asText();
System.out.println(“Username = “+username);
} catch (Exception e)
{
Throw new Exception (e.getMessage());
}
Return OutputEvent.fromBytes(
username.getBytes(), // Data
OutputEvent.Status.Success,// Any numeric HTTP status code can be used here
"text/plain");
Der Benutzername kann innerhalb der Funktion verwendet werden, um Geschäftslogik nach Bedarf zu implementieren. Rollen sind im Authentifizierungstoken nicht verfügbar, können jedoch mit REST-APIs von Oracle Identity Cloud Service abgefragt werden.
Wenn Oracle API Gateway die Funktion aufruft, werden auch verschiedene nützliche Header gesendet. Diese Header können mit der API der Funktion gelesen werden. Im Developer Kit für Funktionen verfügbare nützliche Header:
Fn-Http-Methode | Die Methode, mit der die Funktion aufgerufen wird (GET/POST/PUT usw.). |
Fn-Http-Request-Url | Die URL, die für den Aufruf der Funktion verwendet wird. Dies umfasst die Abfrageparameter. |
Fn-Http-Henutzer-Agent | Client-Details, wie z. B. Betriebssystem, Hersteller und Version. |
Beispiel: Mit einer Kombination aus Fn-Http-Method und Fn-Http-Request-Url können Sie einen Router innerhalb Ihres Codes implementieren, sodass sich Ihre Funktion von den davon unterscheidet, wie sie aufgerufen wurde (wie PUT, PATCH usw.). Dieser Ansatz wird häufig als Muster “Serverloser Service” bezeichnet und hat den Vorteil, dass der Entwickler weniger Funktionen verwalten muss. Jede Funktion verfügt über einen wenig Router, der festlegt, was sie tun muss.
public OutputEvent handleRequest(InputEvent rawInput, HTTPGatewayContext hctx) throws JsonProcessingException {
String httpMethod = hctx.getMethod();
String httpRequestURI = hctx.getRequestURL();
// etc
}
Info zum Aufrufen von Oracle Fusion Applications Cloud Service mit einem JWT-Assertion-Zugriffstoken
Sie müssen die JWT-Assertion aus Oracle Functions implementieren, indem Sie das Subject im eingehenden Autorisierungsheader verwenden.
Die mit diesem Lösungsplaybook bereitgestellte Beispielfunktion kann diesen Geschäftsprozess mit einer Helper-Library namens idcsOAuthAsserter
ausführen. Die Helper-Library führt den vollständigen OAuth Assertion Flow durch, indem ein Austausch von Bearer-Token durchgeführt wird, bevor Oracle Fusion Applications Cloud Service aufgerufen wird. Diese Bibliothek ist in die Beispielfunktion integriert.
Die Funktion erfordert den Private Key und das öffentliche Zertifikat, um die Benutzer- und Client-Assertions zu erstellen, mit denen Oracle Identity Cloud Service aufgerufen wird, um ein neues Bearer-Zugriffstoken mit der OAuth JWT-Assertion zu erstellen.
Die idcsOAuthAsserter
-Library erfordert einige Eigenschaften, die Sie in der Funktionskonfiguration definieren können. Alle Variablen in der folgenden Tabelle sind obligatorisch:
Konfig-Name | Beschreibung | Beispiel |
---|---|---|
IDCS_URL | Ihre Oracle Identity Cloud Service-Instanz-URL | https://<Ihr Identitätscloudhostname.identity.oraclecloud.com> |
CLIENT_ID | Ihre Oracle Identity Cloud Service-Anwendungsclient-ID, die mit Oracle Functions und Oracle API Gateway verknüpft ist | 1a2b3c4d5e6f7g8h9i01j2k3l4m5o6p7 |
KEY_ID | Alias der Zertifikate, die in die Trusted Oracle Identity Cloud Service-Anwendung importiert wurden | fnassertionkey |
GELTUNGSBEREICH | Dieser Geltungsbereich muss mit der OAuth-Zielressource übereinstimmen, bei der es sich um die Oracle Identity Cloud Service-Anwendung handelt, die mit Ihrem Oracle Fusion Applications Cloud Service verknüpft ist | urn:opc:resource:fa:instanceid=xxxxxxurn:opc:resource:consumer:: all https://my_fusion_hostname:443/ |
ZIELGRUPPE | Zielgruppen für den Assertion-Prozess. Trennen Sie mehrere Werte durch Kommas. | myhostname.identity.oraclecloud.com, https://myfusionservice.dc1.oraclecloud.com |
IDDOMAIN | Name des Mandanten der Oracle Fusion Applications Cloud Service-Instanz | mytenant |
Die Funktion erfordert außerdem Konfigurationseigenschaften, um auf weitere Assertions im Zusammenhang mit idcsOAuthAsserter
zuzugreifen. Die JWT-Assertion erfordert ein Zertifikat und einen Private Key, um die Client- und Benutzer-Assertions zu generieren. Die Funktion ruft den Keystore mit der in V_KEYSTORE
angegebenen OCID ab. Der Alias zum Abrufen dieser Informationen muss mit dem KEY_ID
-Wert in der Konfiguration übereinstimmen. Die Passphrase für Keystore und Private Key muss aus dem Oracle Cloud Infrastructure Vault Secrets Service mit den OCIDs abgerufen werden, die in V_KS_PASS
und V_PK_PASS
angegeben werden.
Konfig-Name | Beschreibung | Beispiel |
---|---|---|
V_KEYSTORE | Secret, das den sicheren gespeicherten Inhalt des Keystores enthält | ocid1.vaultsecret.oc1.dc1. xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxx |
V_KS_PASS | Geheim mit dem sicheren gespeicherten Kennwort für den Keystore | ocid1.vaultsecret.oc1.dc1. xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxx |
V_PK_PASS | Geheim mit dem sicheren gespeicherten Kennwort für den Private Key | ocid1.vaultsecret.oc1.dc1. xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxx |
Ein zusätzlicher unterstützter Konfigurationswert ist die Eigenschaft USE_CACHE_TOKEN
, die standardmäßig auf True
gesetzt ist. Mit dieser Eigenschaft können Sie das generierte Oracle Identity Cloud Service-Assertion-Token in zukünftigen Aufrufen von Oracle Fusion Applications Cloud Service speichern, solange das Token gültig bleibt. Das gecachte Token wird vor der Verwendung validiert, indem das Subject mit dem eingehenden Token verglichen und die Ablaufzeit geprüft wird, um zu prüfen, ob es noch gültig ist. Andernfalls wird ein neues Zugriffstoken mit der OAuth-Assertion angefordert. Dieses Feature kann deaktiviert werden, indem USE_CACHE_TOKEN
auf False
gesetzt wird.
Die zu implementierende Funktion kann SecurityHelper object
aus der idcsOAuthAsserter
-Bibliothek verwenden, um das Subject aus dem Header access-token
zu extrahieren, ein neues Bearer-Zugriffstoken mit OAuth JWT-Assertion zu generieren und eine Anforderung mit dem neuen Zugriffstoken Authorization
an Oracle Fusion Applications Cloud Service zu senden.
Die Funktion saasopportunitiesfn
im Quellcodebeispiel ist bereits in die idcsOAuthAsserter
-Bibliothek integriert. Das folgende Code-Snippet ist in der Methode handleRequest
der Beispielfunktion verfügbar. Hier wird gezeigt, wie die Objekte von idcsOAuthAsserter
initialisiert und wie Token mit Oracle Identity Cloud Service ersetzt werden:
// Full Oauth scenario Perform exchange of tokens
if(fullOAauth) {
LOGGER.log(Level.INFO, "Full Oauth Assertion scenario - Perform exchange of tokens");
SecurityHelper idcsSecurityHelper = new SecurityHelper(context) // Initialize SecurityHelper with RuntimeContext
.setOciRegion(Region.US_PHOENIX_1) // Specify the OCI region, used to retrieve Secrets.
.extractSubFromJwtTokenHeader(rawInput); // Extracts the subject from Token in Fn-Http-H-Authorization.
// Get OAuth Access token with JWT Assertion using the principal extracted from Fn-Http-H-Access-Token Header
jwttoken = idcsSecurityHelper.getAssertedAccessToken();
LOGGER.log(Level.INFO, "Successfully token retrived with IDCS Assertion");
LOGGER.log(Level.FINEST, "Access Token from assertion [" + jwttoken + "]");
}
Beachten Sie, dass das Objekt SecurityHelper
mit einem Kontextobjekt vom Typ RuntimeContext
initialisiert wird. Damit wird SecurityHelper
mit der Konfiguration für die idcsOAuthAsserter
Helper-Library initialisiert.
Das Beispiel für die saasopportunitiesfn
-Funktion ist auf die Verwendung des Bereichs US_PHOENIX_1
gesetzt. Sie müssen also den Bereich in der Methode setOciRegion
ändern, die im Snippet angezeigt wird, um auf Ihre Region zu verweisen.
SecurityHelper
verfügt außerdem über die Methode extractSubFromJwtTokenHeader
, die das Objekt InputEvent
aus der Methode handleRequest
Function übernimmt, um das Bearer-Token zu extrahieren, das im API Gateway Authorization
-Header enthalten ist. Danach sollten Sie ein Zugriffstoken als Ergebnis der Oracle Identity Cloud Service-Assertion abrufen können.
Weitere Informationen zur Verwendung und Integration von idcsOAuthAsserter
mit einer Funktion finden Sie in der README-Datei für idcsOAuthAsserter
im Code-Repository mit dem herunterladbaren Codebeispiel, das diesem Lösungswiedergabebuch zugeordnet ist.
Konfigurationsparameter festlegen
Die Oracle Functions-Umgebung stellt eine sehr nützliche Funktionalität bereit, mit der Sie einige Parameter innerhalb der Oracle Cloud Infrastructure-Umgebung definieren und sie dann aus Ihrem Code referenzieren können.
In diesem Anwendungsfall legen Sie die Fusion- und OverrideJWT-Token-URLs und ein Flag namens full_oauth
als Parameter fest, die in Ihrem Code verwendet werden. So fügen Sie Parameter hinzu:
Im Code können Sie mit dem Funktions-SDK auf diese Konfigurationsvariablen zugreifen, indem Sie eine spezielle Java-Anmerkung (@FnConfiguration
) verwenden und über die Kontextvariable auf die Parameter zugreifen:
private String jwtoverride = "";
private String fusionHostname = "";
private String fnURIBase ="/fnsaaspoc/opportunities";
/**
* @param ctx : Runtime context passed in by Fn
*/
@FnConfiguration
public void config(RuntimeContext ctx) {
fusionHostname = ctx.getConfigurationByKey("fusionhost").orElse("NOTSET");
jwtoverride = ctx.getConfigurationByKey("overridejwt").orElse("NOTSET");
fullOAauth = Boolean.parseBoolean(ctx.getConfigurationByKey("full_oauth").orElse("false"));
LOGGER.info("Configuration read : jwt=" + jwtoverride + " saasurl=" + fusionHostname);
}
Da diese Lösung außerdem die idcsOAuthAsserter
-Helper Library verwendet, müssen Sie die spezifischen Variablen, die in dem vorherigen Abschnitt beschrieben wurden, in der Funktionskonfiguration angeben, um die Zugriffstoken mit der Oracle Identity Cloud Service OAuth-Assertion auszutauschen. Da für diesen Prozess mehrere obligatorische Konfigurationen erforderlich sind, wird empfohlen, dass Sie die Funktionskonfiguration mit dem jaml-Dateiansatz festlegen. Beispiel:
config:
AUDIENCE: <AUDIENCE_VALUES>
CLIENT_ID: <YOUR_CLIENT_ID>
IDCS_URL: <YOUR_IDCS_URL>
IDDOMAIN: <YOUR_FA_TENANT_NAME>
KEY_ID: <YOUR_IDCS_URL>
SCOPE: <FA_RESOURCE_SCOPE>
V_KEYSTORE: <YOUR_KS_OCID>
V_KS_PASS: <YOUR_KSPASS_OCID>
V_PK_PASS: <YOUR_PKPASS_OCID>
fusionhost: <value>
overridejwt: <value>
full_oauth: <value>
Benutzerauthentifizierungstoken an Fusion Applications übergeben
Ihre Funktion muss das Benutzerauthentifizierungstoken für sichere REST-API-Interaktionen verarbeiten.
Wenn die Funktion aufgerufen wird, wird auch eine Header-Variable “Authorization” gesendet, die ein Authentifizierungstoken enthalten würde. Dieses Token wird vom Identity Server der aufrufenden Anwendung generiert, bei dem es sich um denselben Identity Server handelt, mit dem die Oracle Cloud Infrastructure-API-Gateway-Funktion die Anforderung validiert.
Die in diesem Lösungswiedergabebuch beschriebene Lösung umfasst, dass Sie die Oracle Identity Cloud Service OAuth JWT-Assertion zur Ausführung des Tokenaustauschs mit der idcsOAuthAsserter
-Helper Library verwenden. Dadurch wird eine zusätzliche Sicherheitsebene für den Aufruf von Oracle Functions zu Oracle Fusion Applications Cloud Service bereitgestellt. Wie im Architekturdiagramm dargestellt, fragt die Funktion mit OAuth JWT-Assertion-Abfragen für das Token ab, das im eingehenden Aufruf vom API-Gateway-Header enthalten ist. Dabei wird sie für ein anderes Token während des Assertion-Prozesses mit Oracle Identity Cloud Service verwendet. Dieses neue Token wird in dem ausgehenden Aufruf des Zielservers ( Oracle Fusion Applications Cloud Service ) verwendet und ( Oracle Fusion Applications Cloud Service ) führt den Aufruf als Benutzer in Oracle Visual Builder aus.
In der bereitgestellten Beispielfunktion (saasopportunitiesfn
) gibt es eine Konfiguration namens full_oauth
, die standardmäßig auf True
gesetzt ist und das Verhalten oben beschrieben wird.
Optional können Sie full_oauth
auf False
festlegen. In diesem Fall fragt die Funktion das Token ab, das im eingehenden Aufruf vom API-Gateway-Header enthalten ist, und verwendet es im ausgehenden Aufruf von Oracle Fusion Applications Cloud Service wieder. Kein zweites Token generiert.
Das folgende Code-Snippet verwendet die Apache HTTP-Library und ruft die Oracle Fusion Applications Cloud Service REST-API mit dem übergebenen Authentifizierungstoken auf.
String fusionURL=”<yourfusionresturl>”;
HttpClient client = HttpClients.custom().build();
HttpUriRequest request = RequestBuilder.get().setUri(fusionURL).
setHeader(HttpHeaders.CONTENT_TYPE, "application/json").
setHeader(HttpHeaders.AUTHORIZATION, "Bearer " + jwtToken).
build();
HttpResponse response = client.execute(request);
responseJson = EntityUtils.toString(response.getEntity());
status = response.getStatusLine().getStatusCode();
Kompilieren und Bereitstellen der Funktion
Erstellen Sie in Oracle Functions eine Anwendung für Ihre Funktion, und stellen Sie anschließend die Funktion bereit.
Definieren Sie optional eine Authentifizierungsfunktion in Oracle Cloud Infrastructure
Oracle Cloud Infrastructure -API-Gateway unterstützt natives IDCS als Authentifizierungsprovider. Das Gateway lässt jedoch auch die Definition einer Funktion zu, die sie aufrufen kann. Optional können Sie mit diesem Feature eine benutzerdefinierte Authentifizierungsfunktion erstellen.
Die benutzerdefinierte Authentifizierungsfunktion empfängt einen Aufruf vom Gateway und übergibt den eingehenden Autorisierungsheader. Wenn die Funktion True zurückgibt, ist der Funktionsaufruf zulässig. Wenn er False zurückgibt, wird die Anforderung mit einem HTTP 401-Fehlercode abgelehnt. Die Funktion wird im Quellcodeformat bereitgestellt und in Funktionen bereitgestellt, die dann über ihre OCID in der GATEWAY-Deployment-Datei der OCI-API referenziert werden. Sie können die OCID erkennen, indem Sie zu der bereitgestellten Funktion in der Konsole navigieren und die zugehörige OCID-Spalte einblenden. Bevor die Funktion bereitgestellt werden kann, müssen Sie die Datei ResourceServerConfig.java
bearbeiten. Damit wird definiert, wie sich die Funktion bei Oracle Identity Cloud Service anmeldet und welche Oracle Identity Cloud Service OAuth-Anwendung verwendet wird.
Das nachstehende Funktionsbeispiel vermeidet hartcodierte sensible Werte wie das Client Secret. In den vier Zeilen unter dem Kommentar // KMS Key for IDCS Client Secret
entschlüsselt der Code das OAuth-Secret mit dem Oracle Cloud Infrastructure-Schlüsselverwaltungs-Feature, Oracle Cloud Infrastructure Vault. Sie geben diese Werte in die Oracle Cloud Infrastructure-Konsole ein, bevor Sie die Funktion bereitstellen.