Service User denied access to Alarm API even with requiredRoles set

Product: Free trial Cumulocity IoT Backend 1018.0.229 on SaaS environment of eu-latest

Problem: I have followed the Java SDK example guide for the iptracker microservice ( /guides/microservice-sdk/java/#microservice-java )

  • via cUrl application is created on tenant, bootstrap user correctly returned, subscription request ok (Status 201 at first try, subsequent calls correctly returns {“error”:“tenants/Duplicate”,“message”:“Application with id ID [type=com_cumulocity_model_idtype_GId, value=98922] is already assigned to the tenant env314296”,“info”:“/guides/reference/rest-implementat
    ion//#a-name-error-reporting-a-error-reporting”} )
  • generated docker image runs locally, container goes up and stays live (health endpoint returns ok), but runtime errors occur.
    Exception are thrown, such as during the periodic microservice subscription event:
2023-10-19 10:04:50.628  WARN 8 --- [subscriptions-0] c.c.m.context.ContextServiceImpl         : execution of task failed within tenant : env314296 - Http status code: 403
{error="security/Forbidden",message="Access is denied",info="<URL>/guides/reference/rest-implementation//#a-name-error-reporting-a-error-reporting",details="null"}
 tenant: env314296 user: service_iptracker-microservice
2023-10-19 10:04:50.629 ERROR 8 --- [subscriptions-0] c.m.s.s.MicroserviceSubscriptionsService : Http status code: 403
{error="security/Forbidden",message="Access is denied",info="<URL>/guides/reference/rest-implementation//#a-name-error-reporting-a-error-reporting",details="null"}
 tenant: env314296 user: service_iptracker-microservice

com.cumulocity.sdk.client.SDKException: Http status code: 403
{error="security/Forbidden",message="Access is denied",info="<URL>/guides/reference/rest-implementation//#a-name-error-reporting-a-error-reporting",details="null"}
 tenant: env314296 user: service_iptracker-microservice
        at com.cumulocity.sdk.client.ResponseParser.checkStatus(ResponseParser.java:81)
        at com.cumulocity.sdk.client.ResponseParser.parse(ResponseParser.java:63)
        at com.cumulocity.sdk.client.RestConnector.parseResponseWithoutId(RestConnector.java:364)
        at com.cumulocity.sdk.client.RestConnector.post(RestConnector.java:270)
        at com.cumulocity.sdk.client.alarm.AlarmApiImpl.create(AlarmApiImpl.java:95)
        at jdk.internal.reflect.GeneratedMethodAccessor33.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137)
        at org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:220)
        at jdk.proxy2/jdk.proxy2.$Proxy131.create(Unknown Source)
        at c8y.example.App.lambda$createAlarm$0(App.java:105)
        at com.cumulocity.microservice.context.ContextServiceImpl.callWithinContext(ContextServiceImpl.java:78)
        **at c8y.example.App.createAlarm(App.java:88)**
        at jdk.internal.reflect.GeneratedMethodAccessor31.invoke(Unknown Source)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:568)
        at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:344)
        at org.springframework.context.event.ApplicationListenerMethodAdapter.processEvent(ApplicationListenerMethodAdapter.java:229)
        at org.springframework.context.event.ApplicationListenerMethodAdapter.onApplicationEvent(ApplicationListenerMethodAdapter.java:166)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169)
        at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143)
        at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:421)
        at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:378)
        at com.cumulocity.microservice.subscription.service.impl.MicroserviceSubscriptionsServiceImpl$1.apply(MicroserviceSubscriptionsServiceImpl.java:62)
        at com.cumulocity.microservice.subscription.service.impl.MicroserviceSubscriptionsServiceImpl.lambda$invokeAdded$6(MicroserviceSubscriptionsServiceImpl.java:186)
        at com.cumulocity.microservice.context.ContextServiceImpl.callWithinContext(ContextServiceImpl.java:78)
        at com.cumulocity.microservice.subscription.service.impl.MicroserviceSubscriptionsServiceImpl.invokeAdded(MicroserviceSubscriptionsServiceImpl.java:186)
        at com.cumulocity.microservice.subscription.service.impl.MicroserviceSubscriptionsServiceImpl.lambda$subscribe$2(MicroserviceSubscriptionsServiceImpl.java:132)
        at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178)
        at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
        at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
        at com.cumulocity.microservice.subscription.service.impl.MicroserviceSubscriptionsServiceImpl.subscribe(MicroserviceSubscriptionsServiceImpl.java:138)
        at com.cumulocity.microservice.subscription.service.impl.MicroserviceSubscriptionScheduler.lambda$schedulePeriodicSubscription$0(MicroserviceSubscriptionScheduler.java:81)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
        at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
        at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:305)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
        at java.base/java.lang.Thread.run(Thread.java:833)

src/main/resources/application.properties:

application.name=iptracker-microservice
server.port=80
C8Y.baseURL=<HTTPS>://env314296.eu-latest.cumulocity.com/
C8Y.bootstrap.tenant=env314296
C8Y.bootstrap.user=servicebootstrap_iptracker-microservice
C8Y.bootstrap.password=<REDACTED>
C8Y.microservice.isolation=MULTI_TENANT

src/main/configuration/cumulocity.json:

{
  "apiVersion": "1",
  "version": "@project.version@",
  "provider": {
    "name": "Cumulocity GmbH"
  },
  "isolation": "MULTI_TENANT",
  "settings": [
    {
      "key": "ipstack.key",
      "defaultValue": "<REDACTED>"
    },
    {
      "key": "tracker.id",
      "defaultValue": "761224"
    }
  ],
  "livenessProbe": {
    "httpGet": {
      "path": "/health"
    },
    "initialDelaySeconds": 60,
    "periodSeconds": 10
  },
  "readinessProbe": {
    "httpGet": {
      "path": "/health",
      "port": 80
    },
    "initialDelaySeconds": 20,
    "periodSeconds": 10
  },
  "requiredRoles": [
    "ROLE_EVENT_READ",
    "ROLE_EVENT_ADMIN",
    "ROLE_ALARM_READ",
    "ROLE_ALARM_ADMIN"
  ],
  "roles": []
}

As per my understanding the ROLE_ALARM_ADMIN should allow me to create alarms, but the service user seems unable to do so

1 Like

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>c8y.example</groupId>
  <artifactId>iptracker-microservice</artifactId>
  <packaging>jar</packaging>
  <version>1.0.0-SNAPSHOT</version>
  <name>iptracker-microservice</name>
  <url>http://maven.apache.org</url>
  <properties>
    <java.version>17</java.version>
    <maven.compiler.source>${java.version}</maven.compiler.source>
    <maven.compiler.target>${java.version}</maven.compiler.target>
    <spring-boot-dependencies.version>2.5.14</spring-boot-dependencies.version>
    <c8y.version>1018.0.229</c8y.version>
    <microservice.name>iptracker-microservice</microservice.name>
  </properties>
  <repositories>
    <repository>
        <id>cumulocity</id>
        <layout>default</layout>
        <url>https://download.cumulocity.com/maven/repository</url>
    </repository>
</repositories>
<pluginRepositories>
    <pluginRepository>
        <id>public</id>
        <url>https://download.cumulocity.com/maven/repository</url>
    </pluginRepository>
</pluginRepositories>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.nsn.cumulocity.clients-java</groupId>
            <artifactId>microservice-dependencies</artifactId>
            <version>${c8y.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
<dependencies>
    <dependency>
        <groupId>com.nsn.cumulocity.clients-java</groupId>
        <artifactId>microservice-autoconfigure</artifactId>
        <version>${c8y.version}</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>net.minidev</groupId>
        <artifactId>json-smart</artifactId>
        <version>2.5.0</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
  </dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <version>${spring-boot-dependencies.version}</version>
            <configuration>
                <mainClass>c8y.example.App</mainClass>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>com.nsn.cumulocity.clients-java</groupId>
            <artifactId>microservice-package-maven-plugin</artifactId>
            <version>${c8y.version}</version>
            <executions>
                <execution>
                    <id>package</id>
                    <phase>package</phase>
                    <goals>
                        <goal>package</goal>
                    </goals>
                    <configuration>
                        <name>${microservice.name}</name>
                        <image>${microservice.name}</image>
                        <encoding>UTF-8</encoding>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
</project>

Hi,

your cumulocity.json differs slightly to the docs. Try setting isolation field in your cumulocity.json to “PER_TENANT”, see Microservice SDK for Java - Cumulocity IoT Guides.

1 Like

I actually assume that the application has been created but the microservice with the manifest wasn’t uploaded resulting in a service user without any global permissions.
Try to upload the microservice before you start it locally.

1 Like

Hello, thank you for the feedback.
Unfortunately the isolation parameter set to the single or multi tenant (like the hello microservice example) does not fix the exception.
Also, since it is the free trial I cannot upload the resulting zip file which maven creates, it failed when I tried due to permissions. Unless there is a way to upload only the manifest, but it doesn’t seem like it.

If the microservice feature is not enabled you cannot test it against your tenant (even not locally only).
You might ask your SAG contact or approach Sales if the microservice features can be enabled for your tenant.

1 Like

Yeah, on the free trial version only the hello-world example can be executed successfully

Hi,
You can run microservice locally with a trial version. You don’t need to upload microservice to the platform, just call API to create an application with the required role then go to the platform and subscribe to it, and then get a bootstrap user.

2 Likes

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.