Skip to content

Writing Server Metadata Security Connectors

The server metadata security connector provides authorization support for the requests made to a specific OMAG Server. It is part of Egeria's metadata security support. Each OMAG Server has its own instance of the connector, configured in the serverSecurityConnection property of its configuration document. The connection is set with a POST request to /open-metadata/admin-services/servers/{serverName}/security/connection.

Interfaces and Base Classes

The interfaces for the metadata security connectors are defined in the metadata-security-apis module in the org.odpi.openmetadata.metadatasecurity Java package. A server metadata security connector implements one or more of these interfaces, depending on which authorization decisions it wishes to make:

Interface Authorization decisions
OpenMetadataServerSecurity Access to the server as a whole: validateUserForServer, validateUserAsServerAdmin, validateUserAsServerOperator and validateUserAsServerInvestigator.
OpenMetadataServiceSecurity Access to a specific service, and an operation on that service: validateUserForService and validateUserForServiceOperation.
OpenMetadataElementSecurity Access to individual open metadata elements and their anchors, for example validateUserForElementRead, validateUserForElementDetailUpdate, validateUserForAnchorMemberAdd, selectConnection and getReadableZonesForUser.
OpenMetadataRepositorySecurity Access to types and instances through the repository services, for example validateUserForTypeCreate, validateUserForEntityRead, validateUserForRelationshipUpdate, validateEntityReferenceCopySave.
OpenMetadataEventsSecurity Filtering of the instance events sent to and received from a cohort: validateInboundEvent and validateOutboundEvent.
OpenMetadataUserSecurity Within a server, the verifier uses this interface to set the zones for a user's elements: getDefaultZonesForUser and getPublishZonesForUser. The interface also maintains user accounts and security access controls, which the platform uses.

The server creates the connector from its connection using the OpenMetadataServerSecurityVerifier class in the metadata-security-server module. The verifier checks which of the interfaces above the connector implements and only passes it the matching requests. A request covered by an interface that the connector does not implement is not checked by the connector, and is allowed. Similarly, if no server security connection is configured, the requests are not checked.

The base classes are in the metadata-security-connectors module in the org.odpi.openmetadata.metadatasecurity.connectors Java package:

  • OpenMetadataSecurityConnector - the common base class for the platform and server security connectors. The connector must extend this class, since the verifier calls its setServerName, setLocalServerUserId and start methods when the server starts. It provides a protected implementation of each validation method that rejects the request, along with protected methods such as throwUnauthorizedServerAccess, throwUnauthorizedServiceAccess, throwUnauthorizedInstanceAccess and throwUnauthorizedZoneChange that log a well-defined audit log message and throw the appropriate exception.
  • OpenMetadataServerSecurityConnector - extends OpenMetadataSecurityConnector and implements AuditLoggingComponent. It is the starting point for a server metadata security connector. Add the interfaces you need to your subclass and implement their methods as public, calling the inherited methods from the base class when access is to be denied.
  • OpenMetadataServerSecurityProvider - the base class for the connector provider. It extends OpenConnectorProviderBase.

Example Implementation

An example implementation of a server metadata security connector is located in the metadata-security-connectors module. The OpenMetadataAccessSecurityConnector implements OpenMetadataPlatformSecurity, OpenMetadataRepositorySecurity, OpenMetadataServerSecurity, OpenMetadataServiceSecurity, OpenMetadataElementSecurity and OpenMetadataUserSecurity, so the same connector can be used as the platform metadata security connector and as the server metadata security connector for each server. It uses an embedded secrets store connector to supply the user accounts and security groups, and uses governance zones to control the visibility of elements. Its connector provider, OpenMetadataAccessSecurityProvider, extends OpenMetadataServerSecurityProvider.

Writing the Connector Provider

Each connector provider extends the following abstract class:

org.odpi.openmetadata.frameworks.connectors.ConnectorProvider

There is a base class that provides much of the implementation for a connector provider:

org.odpi.openmetadata.frameworks.connectors.ConnectorProviderBase

and a subclass of it that sets up the connector provider from a single description of the connector:

org.odpi.openmetadata.frameworks.connectors.OpenConnectorProviderBase

These base classes assume:

  • There is a single connector implementation class for the connector.
  • The connector is instantiated with the default constructor. This means all of its configuration information is contained in the Connection object supplied on the initialize() method.

If your connector implementation matches these requirements, its connector provider implementation need only implement a constructor to configure the base class's function with details of itself and the Java class of the connector it needs using:

  • a GUID for the connector type
  • a qualified name and display name for the connector type.
  • a description of what the connector is for and how to configure it.
  • the connector class it instantiates.
  • a list of the additional properties, configuration properties and secured properties needed to configure instances of the connector.
  • a description of the connector for its audit log (if the connector implements AuditLoggingComponent).

Use the base class for your type of connector

Many types of connector have their own connector provider base class that extends OpenConnectorProviderBase, for example IntegrationConnectorProvider for integration connectors and OMRSRepositoryConnectorProviderBase for repository connectors. Extend the base class for the type of connector you are writing.

Using OpenConnectorProviderBase

The descriptive information about the connector is supplied through an implementation of the OpenConnectorDefinition interface. This is typically an enum that describes all the connectors in a module. Egeria's own connectors are described in the EgeriaOpenConnectorDefinition enum in the org.odpi.openmetadata.adapters.connectors package. An OpenConnectorDefinition returns:

  • getConnectorComponentId() - unique identifier of the connector for the audit log.
  • getConnectorTypeGUID() - unique identifier of the connector type.
  • getConnectorQualifiedName(), getConnectorDisplayName(), getConnectorDescription() and getConnectorWikiPage() - descriptive information for the connector type and audit log.
  • getConnectorProviderClassName() - the class name of the connector provider. OpenConnectorProviderBase checks that this matches the class of the connector provider being constructed.
  • getConnectorDevelopmentStatus() - the ComponentDevelopmentStatus of the connector.
  • getSupportedAssetTypeName() and getSupportedDeployedImplementationType() - the type of asset and the deployed implementation type that the connector works with.
  • getComponentDescription() - the AuditLogReportingComponent for the connector's audit log messages.

The connector provider then passes this definition to the OpenConnectorProviderBase constructor, along with the connector class name and the names of its recognized configuration properties. The constructor builds the connector type and audit log component description from these values.

/**
 * XXXStoreProvider is the OCF connector provider for the XXX connector.
 */
public class XXXStoreProvider extends OpenConnectorProviderBase
{
    /*
     * Define the name of the connector implementation.
     */
    private static final String connectorClassName = "packagename.XXXStoreConnector";

    /*
     * Define the name of configuration properties.
     */
    public static final String TEMPLATE_QUALIFIED_NAME_CONFIGURATION_PROPERTY = "templateQualifiedName";

    /**
     * Constructor used to initialize the ConnectorProviderBase class.
     */
    public XXXStoreProvider()
    {
        super(MyOrgConnectorDefinition.XXX_STORE_CONNECTOR,
              connectorClassName,
              List.of(TEMPLATE_QUALIFIED_NAME_CONFIGURATION_PROPERTY));
    }
}

There is also a constructor that takes the list of interfaces that the connector supports and a description of the data format that it expects. After calling super(...), the constructor may set up the supportedTechnologyTypes, supportedConfigurationProperties and supportedTemplateTypes variables inherited from ConnectorProvider.

Example: BasicFileStoreProvider

The BasicFileStoreProvider passes EgeriaOpenConnectorDefinition.BASIC_FILE_STORE_CONNECTOR, its connector class name and the BasicFileStore interface to OpenConnectorProviderBase, and then sets supportedTechnologyTypes to show that it works with files.

Using ConnectorProviderBase directly

Alternatively, the connector provider can extend ConnectorProviderBase and set up the connector type and component description itself.

/**
 * XXXStoreProvider is the OCF connector provider for the XXX connector.
 */
public class XXXStoreProvider extends ConnectorProviderBase
{
    /*
     * Unique identifier of the connector for the audit log.
     */
    private static final int    connectorComponentId   = 10001; /* Add unique number here */

    /*
     * Unique identifier for the connector type.
     */
    private static final String connectorTypeGUID      = "Add unique GUID here";

    /*
     * Descriptive information about the connector for the connector type and audit log.
     */
    private static final String connectorQualifiedName = "MyOrg:XXXStoreConnector";
    private static final String connectorDisplayName   = "XXX Store Connector";
    private static final String connectorDescription   = "Connector supports ... add details here.";
    private static final String connectorWikiPage      = "Add url to documentation here";


    /*
     * Define the name of the connector implementation.
     */
    private static final String connectorClassName = "packagename.XXXStoreConnector";

    /*
     * Define the name of configuration properties.
     */
    public static final String TEMPLATE_QUALIFIED_NAME_CONFIGURATION_PROPERTY = "templateQualifiedName";

    /**
     * Constructor used to initialize the ConnectorProviderBase class.
     */
    public XXXStoreProvider()
    {
        super();

        /*
         * Set up the class name of the connector that this provider creates.
         */
        super.setConnectorClassName(connectorClassName);

        /*
         * Set up the connector type that should be included in a connection used to configure this connector.
         */
        ConnectorType connectorType = new ConnectorType();
        connectorType.setGUID(connectorTypeGUID);
        connectorType.setQualifiedName(connectorQualifiedName);
        connectorType.setDisplayName(connectorDisplayName);
        connectorType.setDescription(connectorDescription);
        connectorType.setConnectorProviderClassName(this.getClass().getName());

        List<String> recognizedConfigurationProperties = new ArrayList<>();
        recognizedConfigurationProperties.add(TEMPLATE_QUALIFIED_NAME_CONFIGURATION_PROPERTY);
        connectorType.setRecognizedConfigurationProperties(recognizedConfigurationProperties);

        super.connectorTypeBean = connectorType;

        /*
         * Set up the component description used in the connector's audit log messages.
         */
        AuditLogReportingComponent componentDescription = new AuditLogReportingComponent();

        componentDescription.setComponentId(connectorComponentId);
        componentDescription.setComponentName(connectorQualifiedName);
        componentDescription.setComponentDescription(connectorDescription);
        componentDescription.setComponentWikiURL(connectorWikiPage);

        super.setConnectorComponentDescription(componentDescription);
    }
}

The connector provider for a server metadata security connector extends OpenMetadataServerSecurityProvider.


Raise an issue or comment below