Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
48474eb
Integrate credentials checks for service and asset levels in initiali…
mariacarmina May 7, 2025
dba3198
skip lint.
mariacarmina May 7, 2025
dcd9e43
Update ci docker logs.
mariacarmina May 7, 2025
fba187a
Fix lint.
mariacarmina May 7, 2025
5e8b77e
Added credentials check for free start compute. Use download endpoint…
mariacarmina May 8, 2025
b6212cb
log error.
mariacarmina May 8, 2025
62873e0
Check if did is provided on free start compute.
mariacarmina May 8, 2025
8a510b1
cleanup logs.
mariacarmina May 8, 2025
9d1a39c
Integrate commands for compute from policy server.
mariacarmina May 12, 2025
fd0e7ac
Fix condition in the test.
mariacarmina May 12, 2025
8a81c81
Debug result.
mariacarmina May 12, 2025
3fa443b
cleanup.
mariacarmina May 12, 2025
e5f7638
print ddo test.
mariacarmina May 12, 2025
ace914c
Updated test.
mariacarmina May 12, 2025
1547a98
cleanup function.
mariacarmina May 12, 2025
fed76d7
Merge branch 'main' into feature/credentials-check-for-compute
mariacarmina May 21, 2025
bc2ee4d
remove initialize compute command. Update initializeCompute handler.
mariacarmina May 21, 2025
cefed63
Enhance code.
mariacarmina May 21, 2025
656b69b
Define dedicated type for policy server when it comes on the handler …
mariacarmina May 22, 2025
04ae7e7
Fix type of policy server on http requests.
mariacarmina May 22, 2025
3b4c42e
Fix conflicts.
mariacarmina May 30, 2025
64fae5e
Merge branch 'main' into feature/credentials-check-for-compute
mariacarmina Jun 18, 2025
a2a9793
Fix commands usage for policy server.
mariacarmina Jun 24, 2025
60258f5
Fix conflicts.
mariacarmina Jun 25, 2025
198f0e3
Fix arguments.
mariacarmina Jun 26, 2025
4f0d41f
resolve conflicts.
mariacarmina Jul 9, 2025
5ab79f9
Fix review.
mariacarmina Jul 9, 2025
1d14e9c
Use ddo.js for DDO fields manipulation.
mariacarmina Jul 10, 2025
b142f89
Update for free start compute.
mariacarmina Jul 10, 2025
ce88067
Update datasets samples.
mariacarmina Jul 10, 2025
dae8fa7
Update branch for cli.
mariacarmina Jul 10, 2025
14e9ebd
Fix datasets samples.
mariacarmina Jul 11, 2025
e338882
Merge branch 'main' into feature/credentials-check-for-compute
mariacarmina Jul 11, 2025
5477ba2
Fix samples and ci.
mariacarmina Jul 11, 2025
c9f6910
Update ddo.js.
mariacarmina Jul 11, 2025
faa9da0
Update lock.
mariacarmina Jul 11, 2025
7e7a3d9
Updated ddo schemas version.
mariacarmina Jul 13, 2025
5ea33f6
Fix samples.
mariacarmina Jul 13, 2025
e5f2068
Add engines for test.
mariacarmina Jul 13, 2025
219e97b
Bring all tests back.
mariacarmina Jul 13, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ jobs:
done

- name: docker logs
run: docker logs ocean-ocean-contracts-1 && docker logs ocean-kindcluster-1 && docker logs ocean-computetodata-1 && docker logs ocean-typesense-1
run: docker logs ocean-contracts-1 && docker logs ocean-typesense-1
if: ${{ failure() }}

- name: Checkout Ocean Node
Expand Down
2 changes: 2 additions & 0 deletions src/@types/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ export interface ComputeInitializeCommand extends Command {
consumerAddress: string
signature?: string
maxJobDuration: number
policyServer?: any // object to pass to policy server
Comment thread
mariacarmina marked this conversation as resolved.
Outdated
}

export interface FreeComputeStartCommand extends Command {
Expand All @@ -195,6 +196,7 @@ export interface FreeComputeStartCommand extends Command {
output?: ComputeOutput
resources?: ComputeResourceRequest[]
maxJobDuration?: number
policyServer?: any // object to pass to policy server
}
export interface PaidComputeStartCommand extends FreeComputeStartCommand {
payment: ComputePayment
Expand Down
77 changes: 76 additions & 1 deletion src/components/core/compute/initialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,15 @@ import {
validateCommandParameters
} from '../../httpRoutes/validateCommands.js'
import { isAddress } from 'ethers'
import { getConfiguration } from '../../../utils/index.js'
import { getConfiguration, isPolicyServerConfigured } from '../../../utils/index.js'
import { sanitizeServiceFiles } from '../../../utils/util.js'
import { FindDdoHandler } from '../handler/ddoHandler.js'
import { isOrderingAllowedForAsset } from '../handler/downloadHandler.js'
import { getNonceAsNumber } from '../utils/nonceHandler.js'
import { C2DEngineDocker, getAlgorithmImage } from '../../c2d/compute_engine_docker.js'
import { DDOManager } from '@oceanprotocol/ddo-js'
import { areKnownCredentialTypes, checkCredentials } from '../../../utils/credentials.js'
import { PolicyServer } from '../../policyServer/index.js'

export class ComputeInitializeHandler extends CommandHandler {
validate(command: ComputeInitializeCommand): ValidateParams {
Expand Down Expand Up @@ -205,6 +207,39 @@ export class ComputeInitializeHandler extends CommandHandler {
}
}
}
// check credentials (DDO level)
let accessGrantedDDOLevel: boolean
if (ddo.credentials) {
// if POLICY_SERVER_URL exists, then ocean-node will NOT perform any checks.
// It will just use the existing code and let PolicyServer decide.
if (isPolicyServerConfigured() && task.policyServer) {
accessGrantedDDOLevel = await (
Comment thread
mariacarmina marked this conversation as resolved.
Outdated
await new PolicyServer().checkStartCompute(
ddo.id,
ddo,
elem.serviceId,
0,
elem.transferTxId,
task.consumerAddress,
task.policyServer
)
).success
} else {
accessGrantedDDOLevel = areKnownCredentialTypes(ddo.credentials)
? checkCredentials(ddo.credentials, task.consumerAddress)
: true
}
if (!accessGrantedDDOLevel) {
CORE_LOGGER.logMessage(`Error: Access to asset ${ddo.id} was denied`, true)
return {
stream: null,
status: {
httpStatus: 403,
error: `Error: Access to asset ${ddo.id} was denied`
}
}
}
}
const service = AssetUtils.getServiceById(ddo, elem.serviceId)
if (!service) {
const error = `Cannot find service ${elem.serviceId} in DDO ${elem.documentId}`
Expand All @@ -216,6 +251,46 @@ export class ComputeInitializeHandler extends CommandHandler {
}
}
}
// check credentials on service level
// if using a policy server and we are here it means that access was granted (they are merged/assessed together)
if (service.credentials) {
let accessGrantedServiceLevel: boolean
if (isPolicyServerConfigured() && task.policyServer) {
// we use the previous check or we do it again
// (in case there is no DDO level credentials and we only have Service level ones)
accessGrantedServiceLevel =
accessGrantedDDOLevel ||
Comment thread
mariacarmina marked this conversation as resolved.
Outdated
(await (
await new PolicyServer().checkStartCompute(
ddo.id,
ddo,
elem.serviceId,
0,
elem.transferTxId,
task.consumerAddress,
task.policyServer
)
).success)
} else {
accessGrantedServiceLevel = areKnownCredentialTypes(service.credentials)
? checkCredentials(service.credentials, task.consumerAddress)
: true
}

if (!accessGrantedServiceLevel) {
CORE_LOGGER.logMessage(
`Error: Access to service with id ${service.id} was denied`,
true
)
return {
stream: null,
status: {
httpStatus: 403,
error: `Error: Access to service with id ${service.id} was denied`
}
}
}
}

const ddoInstance = DDOManager.getDDOClass(ddo)
const { chainId: ddoChainId, nftAddress } = ddoInstance.getDDOFields()
Expand Down
179 changes: 178 additions & 1 deletion src/components/core/compute/startCompute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,16 @@ import { decrypt } from '../../../utils/crypt.js'
// import { verifyProviderFees } from '../utils/feesHandler.js'
import { Blockchain } from '../../../utils/blockchain.js'
import { validateOrderTransaction } from '../utils/validateOrders.js'
import { getConfiguration } from '../../../utils/index.js'
import { getConfiguration, isPolicyServerConfigured } from '../../../utils/index.js'
import { sanitizeServiceFiles } from '../../../utils/util.js'
import { FindDdoHandler } from '../handler/ddoHandler.js'
// import { ProviderFeeValidation } from '../../../@types/Fees.js'
import { isOrderingAllowedForAsset } from '../handler/downloadHandler.js'
import { DDOManager } from '@oceanprotocol/ddo-js'
import { getNonceAsNumber, checkNonce, NonceResponse } from '../utils/nonceHandler.js'
import { createHash } from 'crypto'
import { PolicyServer } from '../../policyServer/index.js'
import { areKnownCredentialTypes, checkCredentials } from '../../../utils/credentials.js'

export class PaidComputeStartHandler extends CommandHandler {
validate(command: PaidComputeStartCommand): ValidateParams {
Expand Down Expand Up @@ -159,6 +161,39 @@ export class PaidComputeStartHandler extends CommandHandler {
}
}
}
// check credentials (DDO level)
let accessGrantedDDOLevel: boolean
if (ddo.credentials) {
// if POLICY_SERVER_URL exists, then ocean-node will NOT perform any checks.
// It will just use the existing code and let PolicyServer decide.
if (isPolicyServerConfigured() && task.policyServer) {
accessGrantedDDOLevel = await (
await new PolicyServer().checkStartCompute(
Comment thread
mariacarmina marked this conversation as resolved.
Outdated
ddo.id,
ddo,
elem.serviceId,
0,
elem.transferTxId,
task.consumerAddress,
task.policyServer
)
).success
} else {
accessGrantedDDOLevel = areKnownCredentialTypes(ddo.credentials)
? checkCredentials(ddo.credentials, task.consumerAddress)
: true
}
if (!accessGrantedDDOLevel) {
CORE_LOGGER.logMessage(`Error: Access to asset ${ddo.id} was denied`, true)
return {
stream: null,
status: {
httpStatus: 403,
error: `Error: Access to asset ${ddo.id} was denied`
}
}
}
}
const service = AssetUtils.getServiceById(ddo, elem.serviceId)
if (!service) {
const error = `Cannot find service ${elem.serviceId} in DDO ${elem.documentId}`
Expand All @@ -170,6 +205,46 @@ export class PaidComputeStartHandler extends CommandHandler {
}
}
}
// check credentials on service level
// if using a policy server and we are here it means that access was granted (they are merged/assessed together)
if (service.credentials) {
let accessGrantedServiceLevel: boolean
if (isPolicyServerConfigured() && task.policyServer) {
// we use the previous check or we do it again
// (in case there is no DDO level credentials and we only have Service level ones)
accessGrantedServiceLevel =
accessGrantedDDOLevel ||
(await (
await new PolicyServer().checkStartCompute(
ddo.id,
ddo,
elem.serviceId,
0,
elem.transferTxId,
task.consumerAddress,
task.policyServer
)
).success)
} else {
accessGrantedServiceLevel = areKnownCredentialTypes(service.credentials)
? checkCredentials(service.credentials, task.consumerAddress)
: true
}

if (!accessGrantedServiceLevel) {
CORE_LOGGER.logMessage(
`Error: Access to service with id ${service.id} was denied`,
true
)
return {
stream: null,
status: {
httpStatus: 403,
error: `Error: Access to service with id ${service.id} was denied`
}
}
}
}

const config = await getConfiguration()
const ddoInstance = DDOManager.getDDOClass(ddo)
Expand Down Expand Up @@ -521,6 +596,108 @@ export class FreeComputeStartHandler extends CommandHandler {
}
}
}
for (const elem of [...[task.algorithm], ...task.datasets]) {
if (!('documentId' in elem)) {
continue
}
const ddo = await new FindDdoHandler(this.getOceanNode()).findAndFormatDdo(
elem.documentId
)
if (!ddo) {
const error = `DDO ${elem.documentId} not found`
return {
stream: null,
status: {
httpStatus: 500,
error
}
}
}
// check credentials (DDO level)
let accessGrantedDDOLevel: boolean
if (ddo.credentials) {
// if POLICY_SERVER_URL exists, then ocean-node will NOT perform any checks.
// It will just use the existing code and let PolicyServer decide.
if (isPolicyServerConfigured() && task.policyServer) {
accessGrantedDDOLevel = await (
await new PolicyServer().checkStartCompute(
Comment thread
mariacarmina marked this conversation as resolved.
Outdated
ddo.id,
ddo,
elem.serviceId,
0,
elem.transferTxId,
task.consumerAddress,
task.policyServer
)
).success
} else {
accessGrantedDDOLevel = areKnownCredentialTypes(ddo.credentials)
? checkCredentials(ddo.credentials, task.consumerAddress)
: true
}
if (!accessGrantedDDOLevel) {
CORE_LOGGER.logMessage(`Error: Access to asset ${ddo.id} was denied`, true)
return {
stream: null,
status: {
httpStatus: 403,
error: `Error: Access to asset ${ddo.id} was denied`
}
}
}
}
const service = AssetUtils.getServiceById(ddo, elem.serviceId)
if (!service) {
const error = `Cannot find service ${elem.serviceId} in DDO ${elem.documentId}`
return {
stream: null,
status: {
httpStatus: 500,
error
}
}
}
// check credentials on service level
// if using a policy server and we are here it means that access was granted (they are merged/assessed together)
if (service.credentials) {
let accessGrantedServiceLevel: boolean
if (isPolicyServerConfigured() && task.policyServer) {
// we use the previous check or we do it again
// (in case there is no DDO level credentials and we only have Service level ones)
accessGrantedServiceLevel =
accessGrantedDDOLevel ||
(await (
await new PolicyServer().checkStartCompute(
ddo.id,
ddo,
elem.serviceId,
0,
elem.transferTxId,
task.consumerAddress,
task.policyServer
)
).success)
} else {
accessGrantedServiceLevel = areKnownCredentialTypes(service.credentials)
? checkCredentials(service.credentials, task.consumerAddress)
: true
}

if (!accessGrantedServiceLevel) {
CORE_LOGGER.logMessage(
`Error: Access to service with id ${service.id} was denied`,
true
)
return {
stream: null,
status: {
httpStatus: 403,
error: `Error: Access to service with id ${service.id} was denied`
}
}
}
}
}
try {
const env = await engine.getComputeEnvironment(null, task.environment)
if (!env) {
Expand Down
38 changes: 38 additions & 0 deletions src/components/policyServer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,44 @@ export class PolicyServer {
return await this.askServer(command)
}

async checkInitializeCompute(
Comment thread
mariacarmina marked this conversation as resolved.
Outdated
documentId: string,
ddo: DDO,
serviceId: string,
consumerAddress: string,
policyServer: any
): Promise<PolicyServerResult> {
return await this.checkInitialize(
documentId,
ddo,
serviceId,
consumerAddress,
policyServer
)
}

async checkStartCompute(
documentId: string,
ddo: DDO,
serviceId: string,
fileIndex: number,
transferTxId: string,
consumerAddress: string,
policyServer: any
): Promise<PolicyServerResult> {
const command = {
action: 'startCompute',
documentId,
ddo,
serviceId,
fileIndex,
transferTxId,
consumerAddress,
policyServer
}
return await this.askServer(command)
}

async passThrough(request: any): Promise<PolicyServerResult> {
return await this.askServer(request)
}
Expand Down
Loading
Loading