/**
 * Copyright (c) 2020, 2021 Oracle and/or its affiliates.  All rights reserved.
 * This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.
 */ param param import { EndpointBuilder } from "../endpoint-builder" ; import { FetchHttpClient } from "../http" ; import AbstractAuthenticationDetailsProvider from "./models/abstract-authentication-details-provider" ; import X509CertificateSupplier from "./models/X509-certificate-supplier" ; import { Region } from "../region" ; import { Realm } from "../realm" ; import AuthUtils from "./helpers/auth-utils" ; import SessionKeySupplier from "./models/session-key-supplier" ; import FederationClient from "./models/federation-client" ; import X509FederationClient from "./X509-federation-client" ; import SessionKeySupplierImpl from "./session-key-supplier" ; import { URLBasedX509CertificateSupplier , ResourceDetails } from "./url-based-x509-certificate-supplier" ; import CircuitBreaker from "../circuit-breaker" ; export default abstract class AbstractFederationClientAuthenticationDetailsProviderBuilder < B extends AbstractFederationClientAuthenticationDetailsProviderBuilder < B , P > , P extends AbstractAuthenticationDetailsProvider > { protected template = "https://auth.{region}.{secondLevelDomain}" ; protected METADATA_SERVICE_BASE_URL = "http://169.254.169.254/opc/v2/" ; private METADATA_AUTH_HEADERS = "Bearer Oracle" ; private AUTHORIZATION = "Authorization" ; protected _metadataBaseUrl = this . METADATA_SERVICE_BASE_URL ; protected _federationEndpoint : string = "" ; protected _leafCertificateSupplier ! : X509CertificateSupplier ; protected _tenancyId : string = "" ; private _purpose : string = "DEFAULT" ; protected region ! : Region ; protected _sessionKeySupplier ! : SessionKeySupplier ; protected _federationClient ! : FederationClient ; protected _intermediateCertificateSuppliers ! : X509CertificateSupplier [ ] ; get metadataBaseUrl ( ) : string { return this . _metadataBaseUrl ; } get federationEndpoint ( ) : string { return this . _federationEndpoint ; } get leafCertificateSupplier ( ) : X509CertificateSupplier { return this . _leafCertificateSupplier ; } get tenancyId ( ) : string { return this . _tenancyId ; } getRegion ( ) { return this . region ; } set metadataBaseUrl ( metadataBaseUrl ) { this . _metadataBaseUrl = metadataBaseUrl ; if ( this . _metadataBaseUrl . substr ( - 1 ) != "/" ) { this . _metadataBaseUrl += "/" ; } } set federationEndpoint ( federationEndpoint ) { this . _federationEndpoint = federationEndpoint ; } set leafCertificateSupplier ( leafCertificateSupplier ) { this . _leafCertificateSupplier = leafCertificateSupplier ; } set tenancyId ( tenancyId ) { this . _tenancyId = tenancyId ; } set purpose ( purpose ) { this . _purpose = purpose ; } set sessionKeySupplier ( sessionKeySupplier ) { this . _sessionKeySupplier = sessionKeySupplier ; } set intermediateCertificateSuppliers ( intermediateCertificateSuppliers ) { this . _intermediateCertificateSuppliers = intermediateCertificateSuppliers ; } return async build ( ) { const sessionKeySupplierToUse = this . _sessionKeySupplier || new SessionKeySupplierImpl ( ) ; this . _sessionKeySupplier = sessionKeySupplierToUse ; this . _federationClient = this . createFederationClient ( this . _sessionKeySupplier ) ; return this . buildProvider ( this . _sessionKeySupplier ) ; } param sessionKeySupplierToUse return protected abstract buildProvider ( sessionKeySupplierToUse ) ; param sessionKeySupplier return protected createFederationClient ( sessionKeySupplier ) { return new X509FederationClient ( this . _federationEndpoint , this . _tenancyId , this . _leafCertificateSupplier , sessionKeySupplier , this . _intermediateCertificateSuppliers , this . _purpose ) ; } /**
     * Auto-detect endpoint and certificate information using Instance metadata.
     */ protected async autoDetectUsingMetadataUrl ( ) { await this . autoDetectEndpointUsingMetadataUrl ( ) ; await this . autoDetectCertificatesUsingMetadataUrl ( ) ; } return protected async autoDetectEndpointUsingMetadataUrl ( ) { if ( this . _federationEndpoint === "" ) { const url = this . _metadataBaseUrl + "instance/region" ; let headers = new Headers ( ) ; headers . append ( "accept" , "text/plain" ) ; headers . append ( "Content-Type" , "application/json" ) ; headers . append ( this . AUTHORIZATION , this . METADATA_AUTH_HEADERS ) ; const httpClient = new FetchHttpClient ( null , CircuitBreaker . internalCircuit ) ; const response = await httpClient . send ( { uri : url , method : "GET" , headers : headers } ) ; const regionStr = await response . text ( ) ; const regionId = Region . getRegionIdFromShortCode ( regionStr ) ; try { this . region = Region . fromRegionId ( regionId ) ; } catch ( e ) { console . log ( `
          failed reason: ${ e },
          Region not supported by this version of the SDK, registering region ${ regionId } under OC1
        ` ) ; this . region = Region . register ( regionId , Realm . OC1 ) ; } try { const endpoint = EndpointBuilder . createEndpointFromRegion ( this . template , this . region ) ; this . _federationEndpoint = endpoint ; } catch ( e ) { throw Error ( `Endpoint for auth service is not known in region ${ this . region }` ) ; } } return this . _federationEndpoint ; } /**
     * Auto detects and configures the certificates needed using Instance metadata.
     *
     */ protected async autoDetectCertificatesUsingMetadataUrl ( ) { try { if ( ! this . _leafCertificateSupplier ) { this . _leafCertificateSupplier = await new URLBasedX509CertificateSupplier ( this . getMetaDataResourceDetail ( "identity/cert.pem" ) , this . getMetaDataResourceDetail ( "identity/key.pem" ) , null ) . refresh ( ) ; } if ( this . _tenancyId === "" ) { this . _tenancyId = AuthUtils . getTenantIdFromCertificate ( this . _leafCertificateSupplier . getCertificateAndKeyPair ( ) . getCertificate ( ) ) ; } if ( ! this . _intermediateCertificateSuppliers ) { this . _intermediateCertificateSuppliers = [ await new URLBasedX509CertificateSupplier ( this . getMetaDataResourceDetail ( "identity/intermediate.pem" ) , null , null ) . refresh ( ) ] ; } } catch ( e ) { throw Error ( "Failed to autoDetectCertificatesUsingMetadataUrl" ) ; } } getMetaDataResourceDetail ( path ) { const url = this . _metadataBaseUrl + path ; let headers = new Headers ( ) ; headers . append ( this . AUTHORIZATION , this . METADATA_AUTH_HEADERS ) ; return new ResourceDetails ( url , headers ) ; } }