Composer의 ThingWorx 모델 정의 > 시스템 > 하위 시스템 > 파일 전송 하위 시스템 > 원격 파일 전송을 위한 선택적 보안 기능 향상
원격 파일 전송을 위한 선택적 보안 기능 향상
원격 파일 전송과 관련된 추가 제어 및 보안을 원하는 고객의 경우 아래의 샘플 엔티티 및 수반하는 구독의 일부 또는 전부를 구현하는 것이 좋습니다.
아래의 첫 번째 엔티티는 데이터 셰이프이며, 관리자가 원하는 원격 파일 전송 빈도와 크기에 대해 원하는 매개 변수를 구성할 수 있도록 해줍니다. 데이터 셰이프는 여러 ThingWorx 사용자(및/또는 그와 관련된 응용 프로그램 키)의 서로 다른 설정을 원하는 대로 구성할 수 있습니다.
두 번째 엔티티는 가치 스트림이며, 사용자당 파일 전송의 크기와 빈도를 기록하기 위해 사용됩니다.
아래의 세 번째 엔티티는 모든 원격 파일 전송 이벤트에 의해 트리거되는 구독을 구현합니다. 구독은 자동으로 다음과 같은 프로세스를 수행합니다.
1. 경고를 제공합니다.
2. 파일 전송을 중지합니다.
3. 특정 파일 전송 빈도를 초과할 때마다 관련 WebSocket 연결을 종료합니다.
* 
아래의 예에서는 로거 문이 설명되어 있고 디버그 전용입니다. 고객은 정보가 불필요하게 노출되지 않도록 생산 환경에서 이 문을 활성화하지 않는 것이 좋습니다.
데이터 셰이프 엔티티
먼저 세 개의 필드인 Size, User, Frequency로 이루어진 데이터 셰이프를 가져오거나 생성합니다. 이렇게 하면 사용자가 허용 가능한 최대 파일 전송 한도를 추적합니다.
<?xml version="1.0" encoding="UTF-8"?>
<!-- This entity is for informational and example purposes only, and you must configure/validate it to ensure that it meets your functional and security requirements. -->
<Entities build="latest" majorVersion="0" minorVersion="0" modelPersistenceProviderPackage="PostgresPersistenceProviderPackage" revision="0" schemaVersion="1045" universal="">
<DataShapes>
<DataShape baseDataShape="" description="DataShape for permissible file transfer limits" documentationContent="" homeMashup="" lastModifiedDate="2020-10-01T00:00:00.000-00:00" name="SizeLimits" projectName="FileTransfer" tags="">
<Owner name="Administrator" type="User" />
<avatar />
<DesignTimePermissions>
<Create />
<Read />
<Update />
<Delete />
<Metadata />
</DesignTimePermissions>
<RunTimePermissions />
<VisibilityPermissions>
<Visibility />
</VisibilityPermissions>
<ConfigurationTableDefinitions />
<ConfigurationTables />
<FieldDefinitions>
<FieldDefinition aspect.isPrimaryKey="false" aspect.minimumValue="1.0" baseType="NUMBER" description="" name="Frequency" ordinal="3" />
<FieldDefinition aspect.isPrimaryKey="false" aspect.minimumValue="1.0" baseType="NUMBER" description="SizeLimit for user in bytes" name="Size" ordinal="1" />
<FieldDefinition aspect.isPrimaryKey="false" baseType="STRING" description="User name" name="User" ordinal="2" />
</FieldDefinitions>
</DataShape>
</DataShapes>
</Entities>
가치 스트림 엔티티
데이터 셰이프를 가져오거나 생성한 후 아래의 엔티티를 가져오거나 생성하여 사용자별 파일 전송 기록을 로깅합니다.
<?xml version="1.0" encoding="UTF-8"?>
<!-- This entity is for informational and example purposes only, and you must configure/validate it to ensure that it meets your functional and security requirements. -->
<Entities build="latest" majorVersion="0" minorVersion="0" modelPersistenceProviderPackage="PostgresPersistenceProviderPackage" revision="0" schemaVersion="1045" universal="">
<Things>
<Thing description="ValueStream to log history of file transfers" documentationContent="" effectiveThingPackage="ValueStreamThing" enabled="true" homeMashup="StreamMashup" identifier="" lastModifiedDate="2020-10-01T00:00:00.000-00:00" name="VS" projectName="FileTransfer" published="false" tags="" thingTemplate="ValueStream" valueStream="">
<Owner name="Administrator" type="User" />
<avatar />
<DesignTimePermissions>
<Create />
<Read />
<Update />
<Delete />
<Metadata />
</DesignTimePermissions>
<RunTimePermissions />
<VisibilityPermissions>
<Visibility />
</VisibilityPermissions>
<ConfigurationTableDefinitions />
<ConfigurationTables>
<ConfigurationTable description="Data Thing Configuration" isMultiRow="false" name="DataThingSettings" ordinal="0">
<DataShape>
<FieldDefinitions>
<FieldDefinition baseType="STRING" description="Persistence Provider Name" name="persistenceProvider" ordinal="0" />
</FieldDefinitions>
</DataShape>
<Rows>
<Row>
<persistenceProvider><![CDATA[ThingworxPersistenceProvider]]></persistenceProvider>
</Row>
</Rows>
</ConfigurationTable>
<ConfigurationTable description="Configurable options to tune Value Stream performance" isMultiRow="false" name="PersistenceProviderCustomSettings" ordinal="2">
<DataShape>
<FieldDefinitions>
<FieldDefinition aspect.friendlyName="Persistence Provider Custom Settings Table" baseType="INFOTABLE" description="Persistence Provider Custom Config Table" name="customConfigTable" ordinal="0" />
</FieldDefinitions>
</DataShape>
<Rows>
<Row>
<customConfigTable>
<infoTable>
<DataShape>
<FieldDefinitions />
</DataShape>
<Rows />
</infoTable>
</customConfigTable>
</Row>
</Rows>
</ConfigurationTable>
</ConfigurationTables>
<ThingShape>
<PropertyDefinitions />
<ServiceDefinitions />
<EventDefinitions />
<ServiceMappings />
<ServiceImplementations />
<Subscriptions />
</ThingShape>
<PropertyBindings />
<RemotePropertyBindings />
<RemoteServiceBindings />
<RemoteEventBindings />
<AlertConfigurations />
<ImplementedShapes />
<ThingProperties />
</Thing>
</Things>
</Entities>
원격 파일 전송 엔티티
마지막으로, 각 파일 전송 이벤트에 의해 트리거되는 아래의 구독이 포함된 사물을 가져오거나 생성합니다.
<?xml version="1.0" encoding="UTF-8"?>
<!-- This entity is for informational and example purposes only, and you must configure/validate it to ensure that it meets your functional and security requirements. -->
<Entities build="latest" majorVersion="0" minorVersion="0" modelPersistenceProviderPackage="PostgresPersistenceProviderPackage" revision="0" schemaVersion="1045" universal="">
<Things>
<Thing description="Thing for regulating Remote File Transfer" documentationContent="" effectiveThingPackage="RemoteThingWithFileTransfer" enabled="true" homeMashup="" identifier="FileRepo@ServerA" lastModifiedDate="2020-10-01T00:00:00.000-00:00" name="RemoteFileTransfer" projectName="FileTransfer" published="false" tags="" thingTemplate="RemoteThingWithFileTransfer" valueStream="VS">
<Owner name="Administrator" type="User" />
<avatar />
<DesignTimePermissions>
<Create />
<Read />
<Update />
<Delete />
<Metadata />
</DesignTimePermissions>
<RunTimePermissions />
<VisibilityPermissions>
<Visibility />
</VisibilityPermissions>
<ConfigurationTableDefinitions />
<ConfigurationTables>
<ConfigurationTable description="Reporting Settings" isMultiRow="false" name="ReportingConfiguration" ordinal="0">
<DataShape>
<FieldDefinitions>
<FieldDefinition aspect.defaultValue="NotReporting" aspect.isPrimaryKey="true" aspect.isReadOnly="false" aspect.thingTemplate="ReportingStrategy" baseType="THINGNAME" description="Strategy to determine health" name="reportingStrategy" ordinal="0" />
</FieldDefinitions>
</DataShape>
<Rows>
<Row>
<reportingStrategy><![CDATA[AlwaysOnReporting]]></reportingStrategy>
</Row>
</Rows>
</ConfigurationTable>
</ConfigurationTables>
<ThingShape>
<PropertyDefinitions>
<PropertyDefinition aspect.cacheTime="0.0" aspect.dataChangeType="VALUE" aspect.isLogged="true" aspect.isPersistent="true" baseType="NUMBER" category="" description="" isLocalOnly="false" name="Administrator" ordinal="2" />
<PropertyDefinition aspect.cacheTime="0.0" aspect.dataChangeType="VALUE" aspect.defaultValue="0.0" aspect.isLogged="true" aspect.isPersistent="true" baseType="NUMBER" category="" description="" isLocalOnly="false" name="EventProp" ordinal="4" />
<PropertyDefinition aspect.cacheTime="0.0" aspect.dataChangeType="VALUE" aspect.dataShape="SizeLimits" aspect.isLogged="false" aspect.isPersistent="true" baseType="INFOTABLE" category="" description="" isLocalOnly="false" name="Users" ordinal="3" />
</PropertyDefinitions>
<ServiceDefinitions>
<ServiceDefinition aspect.isAsync="false" category="" description="" isAllowOverride="false" isLocalOnly="false" isOpen="false" isPrivate="false" name="s1">
<ResultType baseType="INFOTABLE" description="" name="result" ordinal="0" />
<ParameterDefinitions />
</ServiceDefinition>
</ServiceDefinitions>
<EventDefinitions />
<ServiceMappings />
<ServiceImplementations>
<ServiceImplementation description="" handlerName="Script" name="s1">
<ConfigurationTables>
<ConfigurationTable description="" isMultiRow="false" name="Script" ordinal="0">
<DataShape>
<FieldDefinitions>
<FieldDefinition baseType="STRING" description="code" name="code" ordinal="0" />
</FieldDefinitions>
</DataShape>
<Rows>
<Row>
<code><![CDATA[var ed = new Date();
var result = me.QueryNumberPropertyHistory({
oldestFirst: undefined /* BOOLEAN */,
maxItems: undefined /* NUMBER */,
endDate: ed /* DATETIME */,
propertyName: "Administrator" /* STRING */,
query: undefined /* QUERY */,
startDate: ed-(24*3600*1000) /* DATETIME */
});]]></code>
</Row>
</Rows>
</ConfigurationTable>
</ConfigurationTables>
</ServiceImplementation>
</ServiceImplementations>
<Subscriptions>
<Subscription description="" enabled="false" eventName="FileTransfer" name="FileTransferSub" source="" sourceProperty="" sourceType="Thing">
<ServiceImplementation description="" handlerName="Script" name="FileTransferSub">
<ConfigurationTables>
<ConfigurationTable description="" isMultiRow="false" name="Script" ordinal="0">
<DataShape>
<FieldDefinitions>
<FieldDefinition baseType="STRING" description="code" name="code" ordinal="0" />
</FieldDefinitions>
</DataShape>
<Rows>
<Row>
<code><![CDATA[var activeTransferJobs = Subsystems["FileTransferSubsystem"].GetActiveTransferJobs();
for each (activeTransferJob in activeTransferJobs.rows) {
var bytesTransferred = activeTransferJob.bytesTransferred;
var transferSize = activeTransferJob.maxSize;
//QueryPropertyHistoryfor24hours
var ed = new Date();
var user = eventData.user;
var last24HrsFileTransfer = me.QueryNumberPropertyHistory({
oldestFirst: undefined /* BOOLEAN */,
maxItems: undefined /* NUMBER */,
endDate: ed /* DATETIME */,
propertyName: user /* STRING */,
query: undefined /* QUERY */,
startDate: ed-(24*3600*1000) /* DATETIME */
});
//Aggregate for 24 hrs.
var totalTransferredBytes = Resources["InfoTableFunctions"].Aggregate({
t: last24HrsFileTransfer,
columns: "value",
aggregates: "SUM"
});
var totalFrequency = last24HrsFileTransfer.length;
var defaultSizeLimitForUser;
var defaultFrequencyForUser;
for each(var user in me.Users.rows){
if(user.User == eventData.user){
defaultSizeLimitForUser = user.Size;
defaultFrequencyForUser = user.Frequency;
}
}
if(totalFrequency>defaultFrequencyForUser || (totalTransferredBytes.SUM_value + transferSize)> defaultSizeLimitForUser){
//logger.error("File Transfer Limit Exceeded : " + activeTransferJob.transferId);
//Send Alert
var eventPropValue = Things['RemoteFileTransfer']['EventProp'];
Things['RemoteFileTransfer']['EventProp'] = eventPropValue + 1;

//Freeze Transfer
//logger.warn("FreezingTransfer : " + activeTransferJob.transferId);
Subsystems["FileTransferSubsystem"].CancelTransfer({
reason: "Surpassed file transfer limit of : " + defaultSizeLimitForUser + " bytes or frequency of " + defaultFrequencyForUser,
transferId: activeTransferJob.transferId
});
//logger.warn("Transfer Freezed : " + activeTransferJob.transferId);
//Closing Endpoint Session for User
result = Subsystems["WSCommunicationsSubsystem"].CloseEndpointSessions({
userName: activeTransferJob.user
});
//logger.warn("Session Closed for userContext : " + activeTransferJob.user);
}
me[eventData.user] = bytesTransferred;
}]]></code>
</Row>
</Rows>
</ConfigurationTable>
</ConfigurationTables>
</ServiceImplementation>
</Subscription>
</Subscriptions>
</ThingShape>
<PropertyBindings />
<RemotePropertyBindings />
<RemoteServiceBindings />
<RemoteEventBindings />
<AlertConfigurations>
<AlertDefinitions name="Administrator" />
<AlertDefinitions name="EventProp" />
<AlertDefinitions name="Users" />
</AlertConfigurations>
<ImplementedShapes />
<ThingProperties>
<Users>
<Value>
<infoTable>
<DataShape>
<FieldDefinitions>
<FieldDefinition aspect.isPrimaryKey="false" aspect.minimumValue="1.0" baseType="NUMBER" description="" name="Frequency" ordinal="3" />
<FieldDefinition aspect.isPrimaryKey="false" aspect.minimumValue="1.0" baseType="NUMBER" description="SizeLimit for user in bytes" name="Size" ordinal="1" />
<FieldDefinition aspect.isPrimaryKey="false" baseType="STRING" description="User name" name="User" ordinal="2" />
</FieldDefinitions>
</DataShape>
<Rows>
<Row>
<Frequency>10.0</Frequency>
<Size>1500000.0</Size>
<User><![CDATA[Administrator]]></User>
</Row>
</Rows>
</infoTable>
</Value>
<Timestamp>2020-10-01T00:00:00.000-00:00</Timestamp>
<Quality>GOOD</Quality>
</Users>
</ThingProperties>
</Thing>
</Things>
</Entities>
도움이 되셨나요?