Hi,
can’t tell why you’re seeing this 400 response, I think we would need code snippets here. Which SDK version are you using?
In your forth step I wouldn’t use bootstrap credentials. These credentials are only meant to retrieve service-users for every subscribed tenant (via /application/currentApplication/subscriptions
endpoint), they shouldn’t be used for other API calls and also not to authenticate a REST request against your service. See the three types of Users in the Microservice docs here.
Below is an example for a multi-tenant microservice that exposes an api endpoint. Once endpoint is hit, it creates a new Managed Object and an External ID in every tenant it is subscribed to.
application.properties:
c8y.version=@c8y.version@
microservice.version=@project.version@
application.name=techforum
application.key=techforum
C8Y.bootstrap.register=true
C8Y.bootstrap.tenant=t1234
C8Y.baseURL=https://t1234.eu-latest.cumulocity.com
C8Y.bootstrap.user=servicebootstrap_techforum
C8Y.bootstrap.password=super-secret-pass
C8Y.microservice.isolation=MULTI_TENANT
logging.level.org.springframework=info
logging.level.root=info
RestController:
@RestController
public class ExampleController {
private ExampleService exampleService;
public ExampleController(ExampleService exampleService) { this.exampleService = exampleService; }
@PostMapping(path = "/createMo", produces = MediaType.TEXT_PLAIN_VALUE)
@PreAuthorize("hasRole('ROLE_INVENTORY_ADMIN') and hasRole('ROLE_IDENTITY_ADMIN')")
public ResponseEntity<String> createMo() {
exampleService.createDevicesWithExternalId();
return ResponseEntity.status(HttpStatus.CREATED).body("Created.");
}
}
Service:
@Service
public class ExampleService {
@Autowired
MicroserviceSubscriptionsService subscriptionsService;
@Autowired
InventoryApi inventoryApi;
@Autowired
IdentityApi identityApi;
public void createDevicesWithExternalId() {
// create MO and external ID in each subscribed tenant
// alternatively, use subscriptionsService.runForEachTenant(Runnable r)
subscriptionsService.getAll().forEach(credentials -> {
subscriptionsService.runForTenant(credentials.getTenant(), () -> {
ManagedObjectRepresentation mo = new ManagedObjectRepresentation();
mo.setType("techforum");
ManagedObjectRepresentation mor = inventoryApi.create(mo);
ExternalIDRepresentation externalIDRepresentation = new ExternalIDRepresentation();
externalIDRepresentation.setExternalId(UUID.randomUUID().toString());
externalIDRepresentation.setType("c8y_Serial");
externalIDRepresentation.setManagedObject(mor);
identityApi.create(externalIDRepresentation);
System.out.println(
String.format(
"Created Managed Object: [id=%s, externalId=%s, owner=%s] in Tenant '%s' with User '%s'",
mor.getId().getValue(), externalIDRepresentation.getExternalId(), mor.getOwner(),
credentials.getTenant(), credentials.getUsername()));
});
});
// or to create in specific tenant:
// subscriptionsService.runForTenant("t12345", Runnable r);
}
}
Now you should be able to start the service and do requests with any User of this tenant (not the bootstrap-user, not the service-user), for example:
curl -X POST http://localhost:8080/createMo -u 't1234/john.doe@cumulocity.com:{password of john.doe}' -v
In case john.doe has the required permissions (see preauthorize annotation), a Managed Object with an External ID is created. If john.doe is lacking the permissions, it will respond 403 Forbidden.
Can you check what’s your response when doing above?
Some notes that might help:
- The request was authorized against your provided User in Controller, but the Object got created by the Service via the Service-User. Thus,
owner
will be your service user.
- To see the permissions of a specific User, you can use the /user/currentUser , the
effectiveRoles
fragment lists the permissions. Can be used for regular users but also for bootstrap- and service-users.
- With setting the log levels in appliation.properties to “debug” you’ll get a verbose output that logs the HTTP calls sent towards the platform.