easydynamics / oscal-rest-service Goto Github PK
View Code? Open in Web Editor NEWImplementation of the OSCAL REST API
License: MIT License
Implementation of the OSCAL REST API
License: MIT License
When using the OSCAL Editor in the all-in-one Docker environment, saving any changes causes the file permissions to change to -rw-r--r--
, making it so that the user within Docker is the only user with write permissions.
I'm assuming that this is an issue with the "save" feature of the REST service itself, but it could very well be an issue with Docker configuration.
As a developer in the OSCAL community, I want to be able to access and contribute to the OSCAL REST Service so that I can develop tools against an implementation of the OSCAL REST API that the ecosystem can use.
As a user of a file-persisted configuration of the oscal-rest-service
, I want to be able to use file names of my choosing rather than the current required UUID file names for OSCAL artifacts so that I and other team members can quickly determine which artifact is which outside of the context of the oscal-rest-service
, i.e., directly examining the folder contents.
jq
for finding the relevant fileWe could consider publishing the oscal-content
folder as a Maven artifact with a different classifier (perhaps default-content
) that could be pulled along with the app jar as a default/testing artifact.
We could consider pulling from oscal-demo-content as a default/testing artifact.
Subtask of EasyDynamics/easygrc#6
As a developer creating apps against the oscal-rest-service
, I want to be able to perform the 'find all' GET
request operations defined in the oscal-rest
specification for the different object types supported by oscal-rest-service
.
GET
requests return all objects supported by the service:
findAll
method that delegates to BaseOscalRepoFileImpl.findAllAs a developer consuming or working with the oscal-rest-service, I want the repository tests and file-based repository implementation to be separated from the REST service application so that I can easily provide alternate implementations without consuming unneeded dependencies and code.
oscal-rest-service
oscal-data-repository-commons
oscal-data-repository-file-impl
When the service is started with persistence.file.*.path
that doesn't exist the repository implementation throws a NullPointerException
rather than the desired DataRetrievalFailureException
which is handled gracefully by the controller.
GET
requestDataRetrievalFailureException
is thrown in the logsNullPointerException
is thrown in the logsAs a user of the OSCAL Rest Service that is accessing local files, I want a more lenient system for accessing my OSCAL files.
Currently, a user of the OSCAL Rest Service that is setting up a local environment is expected to create an OSCAL content directory with a specific directory structure (see the all-in-one deployment README). The directory structure is simple enough, but if a user includes any files that are not properly formatted OSCAL JSON files, a 500 error is given with little feedback to the user.
There are several ways this can occur:
catalogs
, component-definitions
, profiles
, or system-security-plans
directories (or their equivalents, if renamed by the user), a corresponding GET request (eg. GET localhost:1234/oscal/v1/system-security-plans
) ignores those files and does not return a 500 error.Hi, big fan of your tools. I was experimenting with this tool recently in the oscal-editor-deployment all in one utility with latest. I get the following errors:
2022-10-07 05:23:43.908 ERROR 1 --- [nio-8080-exec-9] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataRetrievalFailureException: Failure in loading Oscal object.; nested exception is java.io.IOException: java.lang.IllegalArgumentException: Unable to set the value of field '_uuid' in class 'gov.nist.secauto.oscal.lib.model.Property'.] with root cause
java.lang.IllegalAccessException: interface gov.nist.secauto.metaschema.binding.model.IBoundNamedInstance cannot access a member of class gov.nist.secauto.oscal.lib.model.Property with modifiers "private"
at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:361) ~[na:na]
at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:591) ~[na:na]
at java.base/java.lang.reflect.Field.checkAccess(Field.java:1075) ~[na:na]
at java.base/java.lang.reflect.Field.set(Field.java:778) ~[na:na]
at gov.nist.secauto.metaschema.binding.model.IBoundNamedInstance.setValue(IBoundNamedInstance.java:156) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.DefaultAssemblyClassBinding.readInternal(DefaultAssemblyClassBinding.java:470) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.DefaultAssemblyClassBinding.readItem(DefaultAssemblyClassBinding.java:381) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.ClassDataTypeHandler.get(ClassDataTypeHandler.java:93) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedModelProperty.readItem(AbstractNamedModelProperty.java:282) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.ListPropertyInfo.readValue(ListPropertyInfo.java:153) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedModelProperty.readInternal(AbstractNamedModelProperty.java:233) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedProperty.read(AbstractNamedProperty.java:87) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.DefaultAssemblyClassBinding.readInternal(DefaultAssemblyClassBinding.java:449) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.DefaultAssemblyClassBinding.readItem(DefaultAssemblyClassBinding.java:381) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.ClassDataTypeHandler.get(ClassDataTypeHandler.java:93) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedModelProperty.readItem(AbstractNamedModelProperty.java:282) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.ListPropertyInfo.readValue(ListPropertyInfo.java:153) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedModelProperty.readInternal(AbstractNamedModelProperty.java:233) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedProperty.read(AbstractNamedProperty.java:87) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.DefaultAssemblyClassBinding.readInternal(DefaultAssemblyClassBinding.java:449) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.DefaultAssemblyClassBinding.readItem(DefaultAssemblyClassBinding.java:381) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.ClassDataTypeHandler.get(ClassDataTypeHandler.java:93) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedModelProperty.readItem(AbstractNamedModelProperty.java:282) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.ListPropertyInfo.readValue(ListPropertyInfo.java:153) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedModelProperty.readInternal(AbstractNamedModelProperty.java:233) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedProperty.read(AbstractNamedProperty.java:87) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.DefaultAssemblyClassBinding.readInternal(DefaultAssemblyClassBinding.java:449) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.DefaultAssemblyClassBinding.readItem(DefaultAssemblyClassBinding.java:381) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.ClassDataTypeHandler.get(ClassDataTypeHandler.java:93) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedModelProperty.readItem(AbstractNamedModelProperty.java:282) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.ListPropertyInfo.readValue(ListPropertyInfo.java:153) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedModelProperty.readInternal(AbstractNamedModelProperty.java:233) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedProperty.read(AbstractNamedProperty.java:87) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.DefaultAssemblyClassBinding.readInternal(DefaultAssemblyClassBinding.java:449) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.DefaultAssemblyClassBinding.readItem(DefaultAssemblyClassBinding.java:381) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.ClassDataTypeHandler.get(ClassDataTypeHandler.java:93) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedModelProperty.readItem(AbstractNamedModelProperty.java:282) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.ListPropertyInfo.readValue(ListPropertyInfo.java:153) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedModelProperty.readInternal(AbstractNamedModelProperty.java:233) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedProperty.read(AbstractNamedProperty.java:87) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.DefaultAssemblyClassBinding.readInternal(DefaultAssemblyClassBinding.java:449) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.DefaultAssemblyClassBinding.readItem(DefaultAssemblyClassBinding.java:381) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.ClassDataTypeHandler.get(ClassDataTypeHandler.java:93) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedModelProperty.readItem(AbstractNamedModelProperty.java:282) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.ListPropertyInfo.readValue(ListPropertyInfo.java:153) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedModelProperty.readInternal(AbstractNamedModelProperty.java:233) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedProperty.read(AbstractNamedProperty.java:87) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.DefaultAssemblyClassBinding.readInternal(DefaultAssemblyClassBinding.java:449) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.DefaultAssemblyClassBinding.readObject(DefaultAssemblyClassBinding.java:345) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.RootAssemblyDefinition.readObject(RootAssemblyDefinition.java:76) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.RootAssemblyDefinition.readRoot(RootAssemblyDefinition.java:244) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.io.json.DefaultJsonDeserializer.deserializeToNodeItemInternal(DefaultJsonDeserializer.java:103) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.io.AbstractDeserializer.deserializeToNodeItem(AbstractDeserializer.java:91) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.io.IDeserializer.deserializeToNodeItem(IDeserializer.java:171) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.io.DefaultBoundLoader.loadInternal(DefaultBoundLoader.java:453) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.io.DefaultBoundLoader.load(DefaultBoundLoader.java:435) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.io.IBoundLoader.load(IBoundLoader.java:261) ~[metaschema-java-binding-0.9.0.jar!/:na]
at gov.nist.secauto.metaschema.binding.io.IBoundLoader.load(IBoundLoader.java:281) ~[metaschema-java-binding-0.9.0.jar!/:na]
at com.easydynamics.oscal.data.repository.file.BaseOscalRepoFileImpl.findById(BaseOscalRepoFileImpl.java:171) ~[oscal-data-repository-file-0.0.1-SNAPSHOT.jar!/:0.0.1-SNAPSHOT]
at com.easydynamics.oscal.data.repository.file.BaseOscalRepoFileImpl.findById(BaseOscalRepoFileImpl.java:36) ~[oscal-data-repository-file-0.0.1-SNAPSHOT.jar!/:0.0.1-SNAPSHOT]
at com.easydynamics.oscal.data.repository.file.BaseOscalRepoFileImpl$$FastClassBySpringCGLIB$$51eb9204.invoke(<generated>) ~[oscal-data-repository-file-0.0.1-SNAPSHOT.jar!/:0.0.1-SNAPSHOT]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.22.jar!/:5.3.22]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.22.jar!/:5.3.22]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.22.jar!/:5.3.22]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.22.jar!/:5.3.22]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ~[spring-tx-5.3.22.jar!/:5.3.22]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.22.jar!/:5.3.22]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.22.jar!/:5.3.22]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.22.jar!/:5.3.22]
at com.easydynamics.oscal.data.repository.file.OscalCatalogRepoFileImpl$$EnhancerBySpringCGLIB$$decf60e6.findById(<generated>) ~[oscal-data-repository-file-0.0.1-SNAPSHOT.jar!/:0.0.1-SNAPSHOT]
at com.easydynamics.oscal.service.impl.BaseOscalObjectServiceImpl.findById(BaseOscalObjectServiceImpl.java:93) ~[oscal-object-service-0.0.1-SNAPSHOT.jar!/:0.0.1-SNAPSHOT]
at com.easydynamics.oscal.service.impl.BaseOscalObjectServiceImpl.findById(BaseOscalObjectServiceImpl.java:21) ~[oscal-object-service-0.0.1-SNAPSHOT.jar!/:0.0.1-SNAPSHOT]
at com.easydynamics.oscalrestservice.api.BaseOscalController.findById(BaseOscalController.java:43) ~[classes!/:0.0.1-SNAPSHOT]
at com.easydynamics.oscalrestservice.api.CatalogController.findById(CatalogController.java:49) ~[classes!/:0.0.1-SNAPSHOT]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.22.jar!/:5.3.22]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.22.jar!/:5.3.22]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.22.jar!/:5.3.22]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.22.jar!/:5.3.22]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.22.jar!/:5.3.22]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.22.jar!/:5.3.22]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1070) ~[spring-webmvc-5.3.22.jar!/:5.3.22]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.22.jar!/:5.3.22]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.22.jar!/:5.3.22]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.22.jar!/:5.3.22]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:655) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.22.jar!/:5.3.22]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.65.jar!/:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.22.jar!/:5.3.22]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.22.jar!/:5.3.22]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.22.jar!/:5.3.22]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.22.jar!/:5.3.22]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.22.jar!/:5.3.22]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.22.jar!/:5.3.22]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1789) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.65.jar!/:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.65.jar!/:na]
at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]
2022-10-07 05:23:48.880 WARN 1 --- [nio-8080-exec-3] g.n.s.m.m.c.c.DefaultConstraintValidator : WARNING: (/catalog/back-matter[1]/resource[73]) The cardinality '0' is below the required minimum '1' for items matching the expression 'rlink|base64'.
2022-10-07 05:23:48.883 WARN 1 --- [nio-8080-exec-3] g.n.s.m.m.c.c.DefaultConstraintValidator : WARNING: (/catalog/back-matter[1]/resource[98]) The cardinality '0' is below the required minimum '1' for items matching the expression 'rlink|base64'.
2022-10-07 05:23:48.883 WARN 1 --- [nio-8080-exec-3] g.n.s.m.m.c.c.DefaultConstraintValidator : WARNING: (/catalog/back-matter[1]/resource[100]) The cardinality '0' is below the required minimum '1' for items matching the expression 'rlink|base64'.
2022-10-07 05:23:48.899 DEBUG 1 --- [nio-8080-exec-3] c.e.o.api.CatalogController : Returning wrapped response of type: java.util.ArrayList
2022-10-07 05:23:48.901 DEBUG 1 --- [ task-4] c.e.o.api.CatalogController : Starting marshalling of object type: java.util.ArrayList
2022-10-07 05:23:51.130 DEBUG 1 --- [ task-4] c.e.o.api.CatalogController : Marshalling complete
It seems you're using the most current liboscal-java, so I assume this is an ongoing issue. I am not sure this is a dupe of #111 or another issue altogether. I do recall reports of, in oscal-cli (and I am not sure this bubbles up from liboscal-java): WARNING
messages at one time said as much might have been returned as errors when wrapped in a CLI context, not just warnings. Could this explain the stack trace and issues with validations crashing the whole thing? I got it to stop crashing once I slimmed down a catalog I wanted to edit in REST Mode to the bare essentials like so. So, no constraint warnings, no crashes!
Not sure how that helps or how to report that bug to NIST and liboscal-java though.
{
"catalog": {
"uuid": "fdac0321-959f-43ec-a91d-322da7d9761c",
"metadata": {
"title": "Electronic Version of NIST SP 800-53 Rev 5 Controls and SP 800-53A Rev 5 Assessment Procedures",
"last-modified": "2022-08-23T10:36:49.1330265-04:00",
"version": "5.1.2",
"oscal-version": "1.0.0",
"props": [
{
"name": "keywords",
"value": "Assessment, assessment plan, assurance, availability, computer security, confidentiality, control, control assessment, cybersecurity, FISMA, information security, information system, integrity, personally identifiable information, OSCAL, Open Security Controls Assessment Language, Privacy Act, privacy controls, privacy functions, privacy requirements, Risk Management Framework, security controls, security functions, security requirements, system, system security"
}
],
"links": [
{
"href": "#c3397cc9-83c6-4459-adb2-836739dc1b94",
"rel": "alternate"
},
{
"href": "#f7cf488d-bc64-4a91-a994-810e153ee481",
"rel": "canonical"
}
],
"roles": [
{
"id": "creator",
"title": "Document creator"
},
{
"id": "contact",
"title": "Contact"
}
],
"parties": [
{
"uuid": "41a93829-b76b-43ec-b9e7-250553511549",
"type": "organization",
"name": "Joint Task Force, Interagency Working Group",
"email-addresses": [
"[email protected]"
],
"addresses": [
{
"addr-lines": [
"National Institute of Standards and Technology",
"Attn: Computer Security Division",
"Information Technology Laboratory",
"100 Bureau Drive (Mail Stop 8930)"
],
"city": "Gaithersburg",
"state": "MD",
"postal-code": "20899-8930"
}
]
}
],
"responsible-parties": [
{
"role-id": "creator",
"party-uuids": [
"41a93829-b76b-43ec-b9e7-250553511549"
]
},
{
"role-id": "contact",
"party-uuids": [
"41a93829-b76b-43ec-b9e7-250553511549"
]
}
]
},
"groups": [
{
"id": "ac",
"class": "family",
"title": "Access Control",
"controls": [
{
"id": "ac-1",
"class": "SP800-53",
"title": "Policy and Procedures",
"params": [
{
"id": "ac-1_prm_1",
"props": [
{
"name": "aggregates",
"ns": "http://csrc.nist.gov/ns/rmf",
"value": "ac-01_odp.01"
},
{
"name": "aggregates",
"ns": "http://csrc.nist.gov/ns/rmf",
"value": "ac-01_odp.02"
}
],
"label": "organization-defined personnel or roles"
},
{
"id": "ac-01_odp.01",
"props": [
{
"name": "label",
"value": "AC-01_ODP[01]",
"class": "sp800-53a"
}
],
"label": "personnel or roles",
"guidelines": [
{
"prose": "personnel or roles to whom the access control policy is to be disseminated is/are defined;"
}
]
},
{
"id": "ac-01_odp.02",
"props": [
{
"name": "label",
"value": "AC-01_ODP[02]",
"class": "sp800-53a"
}
],
"label": "personnel or roles",
"guidelines": [
{
"prose": "personnel or roles to whom the access control procedures are to be disseminated is/are defined;"
}
]
},
{
"id": "ac-01_odp.03",
"props": [
{
"name": "alt-identifier",
"value": "ac-1_prm_2"
},
{
"name": "label",
"value": "AC-01_ODP[03]",
"class": "sp800-53a"
}
],
"select": {
"how-many": "one-or-more",
"choice": [
"organization-level",
"mission/business process-level",
"system-level"
]
}
},
{
"id": "ac-01_odp.04",
"props": [
{
"name": "alt-identifier",
"value": "ac-1_prm_3"
},
{
"name": "label",
"value": "AC-01_ODP[04]",
"class": "sp800-53a"
}
],
"label": "official",
"guidelines": [
{
"prose": "an official to manage the access control policy and procedures is defined;"
}
]
},
{
"id": "ac-01_odp.05",
"props": [
{
"name": "alt-identifier",
"value": "ac-1_prm_4"
},
{
"name": "label",
"value": "AC-01_ODP[05]",
"class": "sp800-53a"
}
],
"label": "frequency",
"guidelines": [
{
"prose": "the frequency at which the current access control policy is reviewed and updated is defined;"
}
]
},
{
"id": "ac-01_odp.06",
"props": [
{
"name": "alt-identifier",
"value": "ac-1_prm_5"
},
{
"name": "label",
"value": "AC-01_ODP[06]",
"class": "sp800-53a"
}
],
"label": "events",
"guidelines": [
{
"prose": "events that would require the current access control policy to be reviewed and updated are defined;"
}
]
},
{
"id": "ac-01_odp.07",
"props": [
{
"name": "alt-identifier",
"value": "ac-1_prm_6"
},
{
"name": "label",
"value": "AC-01_ODP[07]",
"class": "sp800-53a"
}
],
"label": "frequency",
"guidelines": [
{
"prose": "the frequency at which the current access control procedures are reviewed and updated is defined;"
}
]
},
{
"id": "ac-01_odp.08",
"props": [
{
"name": "alt-identifier",
"value": "ac-1_prm_7"
},
{
"name": "label",
"value": "AC-01_ODP[08]",
"class": "sp800-53a"
}
],
"label": "events",
"guidelines": [
{
"prose": "events that would require procedures to be reviewed and updated are defined;"
}
]
}
],
"props": [
{
"name": "label",
"value": "AC-1"
},
{
"name": "label",
"value": "AC-01",
"class": "sp800-53a"
},
{
"name": "sort-id",
"value": "ac-01"
}
],
"links": [],
"parts": [
{
"id": "ac-1_smt",
"name": "statement",
"parts": [
{
"id": "ac-1_smt.a",
"name": "item",
"props": [
{
"name": "label",
"value": "a."
}
],
"prose": "Develop, document, and disseminate to {{ insert: param, ac-1_prm_1 }}:",
"parts": [
{
"id": "ac-1_smt.a.1",
"name": "item",
"props": [
{
"name": "label",
"value": "1."
}
],
"prose": "{{ insert: param, ac-01_odp.03 }} access control policy that:",
"parts": [
{
"id": "ac-1_smt.a.1.a",
"name": "item",
"props": [
{
"name": "label",
"value": "(a)"
}
],
"prose": "Addresses purpose, scope, roles, responsibilities, management commitment, coordination among organizational entities, and compliance; and"
},
{
"id": "ac-1_smt.a.1.b",
"name": "item",
"props": [
{
"name": "label",
"value": "(b)"
}
],
"prose": "Is consistent with applicable laws, executive orders, directives, regulations, policies, standards, and guidelines; and"
}
]
},
{
"id": "ac-1_smt.a.2",
"name": "item",
"props": [
{
"name": "label",
"value": "2."
}
],
"prose": "Procedures to facilitate the implementation of the access control policy and the associated access controls;"
}
]
},
{
"id": "ac-1_smt.b",
"name": "item",
"props": [
{
"name": "label",
"value": "b."
}
],
"prose": "Designate an {{ insert: param, ac-01_odp.04 }} to manage the development, documentation, and dissemination of the access control policy and procedures; and"
},
{
"id": "ac-1_smt.c",
"name": "item",
"props": [
{
"name": "label",
"value": "c."
}
],
"prose": "Review and update the current access control:",
"parts": [
{
"id": "ac-1_smt.c.1",
"name": "item",
"props": [
{
"name": "label",
"value": "1."
}
],
"prose": "Policy {{ insert: param, ac-01_odp.05 }} and following {{ insert: param, ac-01_odp.06 }} ; and"
},
{
"id": "ac-1_smt.c.2",
"name": "item",
"props": [
{
"name": "label",
"value": "2."
}
],
"prose": "Procedures {{ insert: param, ac-01_odp.07 }} and following {{ insert: param, ac-01_odp.08 }}."
}
]
}
]
},
{
"id": "ac-1_gdn",
"name": "guidance",
"prose": "Access control policy and procedures address the controls in the AC family that are implemented within systems and organizations. The risk management strategy is an important factor in establishing such policies and procedures. Policies and procedures contribute to security and privacy assurance. Therefore, it is important that security and privacy programs collaborate on the development of access control policy and procedures. Security and privacy program policies and procedures at the organization level are preferable, in general, and may obviate the need for mission- or system-specific policies and procedures. The policy can be included as part of the general security and privacy policy or be represented by multiple policies reflecting the complex nature of organizations. Procedures can be established for security and privacy programs, for mission or business processes, and for systems, if needed. Procedures describe how the policies or controls are implemented and can be directed at the individual or role that is the object of the procedure. Procedures can be documented in system security and privacy plans or in one or more separate documents. Events that may precipitate an update to access control policy and procedures include assessment or audit findings, security incidents or breaches, or changes in laws, executive orders, directives, regulations, policies, standards, and guidelines. Simply restating controls does not constitute an organizational policy or procedure."
},
{
"id": "ac-1_obj",
"name": "assessment-objective",
"props": [
{
"name": "label",
"value": "AC-01",
"class": "sp800-53a"
}
],
"parts": [
{
"id": "ac-1_obj.a",
"name": "assessment-objective",
"props": [
{
"name": "label",
"value": "AC-01a.",
"class": "sp800-53a"
}
],
"parts": [
{
"id": "ac-1_obj.a-1",
"name": "assessment-objective",
"props": [
{
"name": "label",
"value": "AC-01a.[01]",
"class": "sp800-53a"
}
],
"prose": "an access control policy is developed and documented;"
},
{
"id": "ac-1_obj.a-2",
"name": "assessment-objective",
"props": [
{
"name": "label",
"value": "AC-01a.[02]",
"class": "sp800-53a"
}
],
"prose": "the access control policy is disseminated to {{ insert: param, ac-01_odp.01 }};"
},
{
"id": "ac-1_obj.a-3",
"name": "assessment-objective",
"props": [
{
"name": "label",
"value": "AC-01a.[03]",
"class": "sp800-53a"
}
],
"prose": "access control procedures to facilitate the implementation of the access control policy and associated controls are developed and documented;"
},
{
"id": "ac-1_obj.a-4",
"name": "assessment-objective",
"props": [
{
"name": "label",
"value": "AC-01a.[04]",
"class": "sp800-53a"
}
],
"prose": "the access control procedures are disseminated to {{ insert: param, ac-01_odp.02 }};"
},
{
"id": "ac-1_obj.a.1",
"name": "assessment-objective",
"props": [
{
"name": "label",
"value": "AC-01a.01",
"class": "sp800-53a"
}
],
"parts": [
{
"id": "ac-1_obj.a.1.a",
"name": "assessment-objective",
"props": [
{
"name": "label",
"value": "AC-01a.01(a)",
"class": "sp800-53a"
}
],
"parts": [
{
"id": "ac-1_obj.a.1.a-1",
"name": "assessment-objective",
"props": [
{
"name": "label",
"value": "AC-01a.01(a)[01]",
"class": "sp800-53a"
}
],
"prose": "the {{ insert: param, ac-01_odp.03 }} access control policy addresses purpose;"
},
{
"id": "ac-1_obj.a.1.a-2",
"name": "assessment-objective",
"props": [
{
"name": "label",
"value": "AC-01a.01(a)[02]",
"class": "sp800-53a"
}
],
"prose": "the {{ insert: param, ac-01_odp.03 }} access control policy addresses scope;"
},
{
"id": "ac-1_obj.a.1.a-3",
"name": "assessment-objective",
"props": [
{
"name": "label",
"value": "AC-01a.01(a)[03]",
"class": "sp800-53a"
}
],
"prose": "the {{ insert: param, ac-01_odp.03 }} access control policy addresses roles;"
},
{
"id": "ac-1_obj.a.1.a-4",
"name": "assessment-objective",
"props": [
{
"name": "label",
"value": "AC-01a.01(a)[04]",
"class": "sp800-53a"
}
],
"prose": "the {{ insert: param, ac-01_odp.03 }} access control policy addresses responsibilities;"
},
{
"id": "ac-1_obj.a.1.a-5",
"name": "assessment-objective",
"props": [
{
"name": "label",
"value": "AC-01a.01(a)[05]",
"class": "sp800-53a"
}
],
"prose": "the {{ insert: param, ac-01_odp.03 }} access control policy addresses management commitment;"
},
{
"id": "ac-1_obj.a.1.a-6",
"name": "assessment-objective",
"props": [
{
"name": "label",
"value": "AC-01a.01(a)[06]",
"class": "sp800-53a"
}
],
"prose": "the {{ insert: param, ac-01_odp.03 }} access control policy addresses coordination among organizational entities;"
},
{
"id": "ac-1_obj.a.1.a-7",
"name": "assessment-objective",
"props": [
{
"name": "label",
"value": "AC-01a.01(a)[07]",
"class": "sp800-53a"
}
],
"prose": "the {{ insert: param, ac-01_odp.03 }} access control policy addresses compliance;"
}
]
},
{
"id": "ac-1_obj.a.1.b",
"name": "assessment-objective",
"props": [
{
"name": "label",
"value": "AC-01a.01(b)",
"class": "sp800-53a"
}
],
"prose": "the {{ insert: param, ac-01_odp.03 }} access control policy is consistent with applicable laws, Executive Orders, directives, regulations, policies, standards, and guidelines;"
}
]
}
]
},
{
"id": "ac-1_obj.b",
"name": "assessment-objective",
"props": [
{
"name": "label",
"value": "AC-01b.",
"class": "sp800-53a"
}
],
"prose": "the {{ insert: param, ac-01_odp.04 }} is designated to manage the development, documentation, and dissemination of the access control policy and procedures;"
},
{
"id": "ac-1_obj.c",
"name": "assessment-objective",
"props": [
{
"name": "label",
"value": "AC-01c.",
"class": "sp800-53a"
}
],
"parts": [
{
"id": "ac-1_obj.c.1",
"name": "assessment-objective",
"props": [
{
"name": "label",
"value": "AC-01c.01",
"class": "sp800-53a"
}
],
"parts": [
{
"id": "ac-1_obj.c.1-1",
"name": "assessment-objective",
"props": [
{
"name": "label",
"value": "AC-01c.01[01]",
"class": "sp800-53a"
}
],
"prose": "the current access control policy is reviewed and updated {{ insert: param, ac-01_odp.05 }};"
},
{
"id": "ac-1_obj.c.1-2",
"name": "assessment-objective",
"props": [
{
"name": "label",
"value": "AC-01c.01[02]",
"class": "sp800-53a"
}
],
"prose": "the current access control policy is reviewed and updated following {{ insert: param, ac-01_odp.06 }};"
}
]
},
{
"id": "ac-1_obj.c.2",
"name": "assessment-objective",
"props": [
{
"name": "label",
"value": "AC-01c.02",
"class": "sp800-53a"
}
],
"parts": [
{
"id": "ac-1_obj.c.2-1",
"name": "assessment-objective",
"props": [
{
"name": "label",
"value": "AC-01c.02[01]",
"class": "sp800-53a"
}
],
"prose": "the current access control procedures are reviewed and updated {{ insert: param, ac-01_odp.07 }};"
},
{
"id": "ac-1_obj.c.2-2",
"name": "assessment-objective",
"props": [
{
"name": "label",
"value": "AC-01c.02[02]",
"class": "sp800-53a"
}
],
"prose": "the current access control procedures are reviewed and updated following {{ insert: param, ac-01_odp.08 }}."
}
]
}
]
}
]
},
{
"id": "ac-1_asm-examine",
"name": "assessment-method",
"props": [
{
"name": "method",
"ns": "http://csrc.nist.gov/ns/rmf",
"value": "EXAMINE"
},
{
"name": "label",
"value": "AC-01-Examine",
"class": "sp800-53a"
}
],
"parts": [
{
"name": "assessment-objects",
"prose": "Access control policy and procedures\n\nsystem security plan\n\nprivacy plan\n\nother relevant documents or records"
}
]
},
{
"id": "ac-1_asm-interview",
"name": "assessment-method",
"props": [
{
"name": "method",
"ns": "http://csrc.nist.gov/ns/rmf",
"value": "INTERVIEW"
},
{
"name": "label",
"value": "AC-01-Interview",
"class": "sp800-53a"
}
],
"parts": [
{
"name": "assessment-objects",
"prose": "Organizational personnel with access control responsibilities\n\norganizational personnel with information security with information security and privacy responsibilities"
}
]
}
]
}
]
}
],
"back-matter": {
"resources": [
{
"uuid": "91f992fb-f668-4c91-a50f-0f05b95ccee3",
"title": "32 CFR 2002",
"citation": {
"text": "Code of Federal Regulations, Title 32, *Controlled Unclassified Information* (32 C.F.R. 2002)."
},
"rlinks": [
{
"href": "https://www.federalregister.gov/documents/2016/09/14/2016-21665/controlled-unclassified-information"
}
]
}
]
}
}
}
Even though it does not seem that we're vulnerable against the recent Log4j2 vulnerability since we have not "switched the default logging system to Log4J2" mentioned by Spring and don't pull in log4j-core
as a dependency, we should still set log4j2.formatMsgNoLookups=true
to further ensure the system won't be vulnerable if for example future dependencies do bring in log4j-core
.
As a developer contributing to the OSCAL REST Service, I want to use the latest liboscal-java
dependency (1.0.1) so that I can implement against the latest API and minimize vulnerabilities.
After starting the service, the first attempt to GET /catalogs
(I have also seen GET /profiles
) fails with a DataRetrievalFailureException
, the root cause of which is an illegal reflective access to properties within the underlying OSCAL object data type. So far, I am not able to reproduce in the tests. In fact, I've actually only been able to reproduce within the oscal-editor-all-in-one
container (so this issue may need to be transferred to that repository)
oscal-editor-all-in-one
container from the current develop
branch of both the REST service and the React apposcal-content
repositoryhttps://localhost:8080
The application navigation bar properly includes all relevant documents and all requests to the REST service returned a 200 status response
One or more document types fail to load, and the server returns a 5xx response for those requests.
The fields that cause the issue don't seem to be consistent. I have seen it fail (as in the example below) with gov.nist.secauto.oscal.lib.model.Parameter
, but with varying attributes. Additionally, Party
is a common failure that I have seen. They're always related to some private
field (as would be expected).
2022-07-06 03:36:33.518 ERROR 1 --- [nio-8080-exec-5] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.DataRetrievalFailureException: Failure in loading Oscal object.; nested exception is java.io.IOException: java.lang.IllegalArgumentException: Unable to set the value of field '_guidelines' in class 'gov.nist.secauto.oscal.lib.model.Parameter'.] with root cause
java.lang.IllegalAccessException: interface gov.nist.secauto.metaschema.binding.model.IBoundJavaField cannot access a member of class gov.nist.secauto.oscal.lib.model.Parameter with modifiers "private"
at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:361) ~[na:na]
at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:591) ~[na:na]
at java.base/java.lang.reflect.Field.checkAccess(Field.java:1075) ~[na:na]
at java.base/java.lang.reflect.Field.set(Field.java:778) ~[na:na]
at gov.nist.secauto.metaschema.binding.model.IBoundJavaField.setValue(IBoundJavaField.java:127) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.DefaultAssemblyClassBinding.readInternal(DefaultAssemblyClassBinding.java:541) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.DefaultAssemblyClassBinding.readItem(DefaultAssemblyClassBinding.java:454) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.ClassDataTypeHandler.get(ClassDataTypeHandler.java:93) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedModelProperty.readItem(AbstractNamedModelProperty.java:229) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.ListPropertyInfo.readValue(ListPropertyInfo.java:153) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedModelProperty.readInternal(AbstractNamedModelProperty.java:180) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedProperty.read(AbstractNamedProperty.java:86) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.DefaultAssemblyClassBinding.readInternal(DefaultAssemblyClassBinding.java:520) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.DefaultAssemblyClassBinding.readItem(DefaultAssemblyClassBinding.java:454) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.ClassDataTypeHandler.get(ClassDataTypeHandler.java:93) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedModelProperty.readItem(AbstractNamedModelProperty.java:229) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.ListPropertyInfo.readValue(ListPropertyInfo.java:153) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedModelProperty.readInternal(AbstractNamedModelProperty.java:180) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedProperty.read(AbstractNamedProperty.java:86) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.DefaultAssemblyClassBinding.readInternal(DefaultAssemblyClassBinding.java:520) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.DefaultAssemblyClassBinding.readItem(DefaultAssemblyClassBinding.java:454) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.ClassDataTypeHandler.get(ClassDataTypeHandler.java:93) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedModelProperty.readItem(AbstractNamedModelProperty.java:229) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.ListPropertyInfo.readValue(ListPropertyInfo.java:153) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedModelProperty.readInternal(AbstractNamedModelProperty.java:180) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.AbstractNamedProperty.read(AbstractNamedProperty.java:86) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.DefaultAssemblyClassBinding.readInternal(DefaultAssemblyClassBinding.java:520) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.DefaultAssemblyClassBinding.readObject(DefaultAssemblyClassBinding.java:418) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.RootAssemblyDefinition.readObject(RootAssemblyDefinition.java:76) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.model.RootAssemblyDefinition.readRoot(RootAssemblyDefinition.java:244) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.io.json.DefaultJsonDeserializer.deserializeToNodeItemInternal(DefaultJsonDeserializer.java:103) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.io.AbstractDeserializer.deserializeToNodeItem(AbstractDeserializer.java:92) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.io.IDeserializer.deserializeToNodeItem(IDeserializer.java:171) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.io.DefaultBoundLoader.loadInternal(DefaultBoundLoader.java:381) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.io.DefaultBoundLoader.load(DefaultBoundLoader.java:364) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.io.IBoundLoader.load(IBoundLoader.java:259) ~[metaschema-java-binding-0.8.1.jar!/:na]
at gov.nist.secauto.metaschema.binding.io.IBoundLoader.load(IBoundLoader.java:279) ~[metaschema-java-binding-0.8.1.jar!/:na]
at com.easydynamics.oscal.data.repository.file.BaseOscalRepoFileImpl.findAll(BaseOscalRepoFileImpl.java:218) ~[oscal-data-repository-file-0.0.1-SNAPSHOT.jar!/:0.0.1-SNAPSHOT]
at com.easydynamics.oscal.data.repository.file.BaseOscalRepoFileImpl$$FastClassBySpringCGLIB$$51eb9204.invoke(<generated>) ~[oscal-data-repository-file-0.0.1-SNAPSHOT.jar!/:0.0.1-SNAPSHOT]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.21.jar!/:5.3.21]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:793) ~[spring-aop-5.3.21.jar!/:5.3.21]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-5.3.21.jar!/:5.3.21]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.21.jar!/:5.3.21]
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ~[spring-tx-5.3.21.jar!/:5.3.21]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.21.jar!/:5.3.21]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:763) ~[spring-aop-5.3.21.jar!/:5.3.21]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:708) ~[spring-aop-5.3.21.jar!/:5.3.21]
at com.easydynamics.oscal.data.repository.file.OscalCatalogRepoFileImpl$$EnhancerBySpringCGLIB$$928b1a0e.findAll(<generated>) ~[oscal-data-repository-file-0.0.1-SNAPSHOT.jar!/:0.0.1-SNAPSHOT]
at com.easydynamics.oscal.service.impl.BaseOscalObjectServiceImpl.findAll(BaseOscalObjectServiceImpl.java:103) ~[oscal-object-service-0.0.1-SNAPSHOT.jar!/:0.0.1-SNAPSHOT]
at com.easydynamics.oscalrestservice.api.BaseOscalController.findAll(BaseOscalController.java:96) ~[classes!/:0.0.1-SNAPSHOT]
at com.easydynamics.oscalrestservice.api.CatalogController.findAll(CatalogController.java:37) ~[classes!/:0.0.1-SNAPSHOT]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-5.3.21.jar!/:5.3.21]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) ~[spring-web-5.3.21.jar!/:5.3.21]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) ~[spring-webmvc-5.3.21.jar!/:5.3.21]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) ~[spring-webmvc-5.3.21.jar!/:5.3.21]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) ~[spring-webmvc-5.3.21.jar!/:5.3.21]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.3.21.jar!/:5.3.21]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1067) ~[spring-webmvc-5.3.21.jar!/:5.3.21]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:963) ~[spring-webmvc-5.3.21.jar!/:5.3.21]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.21.jar!/:5.3.21]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.3.21.jar!/:5.3.21]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:655) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.21.jar!/:5.3.21]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:764) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:227) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.64.jar!/:na]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.3.21.jar!/:5.3.21]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.21.jar!/:5.3.21]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.3.21.jar!/:5.3.21]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.21.jar!/:5.3.21]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.3.21.jar!/:5.3.21]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) ~[spring-web-5.3.21.jar!/:5.3.21]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:189) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:162) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:135) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:360) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:399) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:890) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1787) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-9.0.64.jar!/:na]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[tomcat-embed-core-9.0.64.jar!/:na]
at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]
I have reproduced in containers built with both Java 11 and Java 17; I have not tried reverting to an older version of liboscal-java
. The fact I can't reproduce when using mvn spring-boot:run
in the oscal-rest-service-app
directory makes this quite a bit trickier to debug.
User error of some kind?
mvn clean install
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] oscal-rest-service-parent [pom]
[INFO] oscal-data-repository-commons [jar]
[INFO] oscal-data-repository-commons-tests [jar]
[INFO] oscal-data-repository-file [jar]
[INFO] oscal-object-service [jar]
[INFO] oscal-rest-service-app [jar]
[INFO]
[INFO] -------------< com.easydynamics:oscal-rest-service-parent >-------------
[INFO] Building oscal-rest-service-parent 0.0.1-SNAPSHOT [1/6]
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ oscal-rest-service-parent ---
[INFO] Deleting /home/degenaro/git/easy-dynamics/oscal-rest-service/target
[INFO]
[INFO] --- maven-checkstyle-plugin:3.1.2:check (validate) @ oscal-rest-service-parent ---
[WARNING] Old version of checkstyle detected. Consider updating to >= v8.30
[WARNING] For more information see: https://maven.apache.org/plugins/maven-checkstyle-plugin/examples/upgrading-checkstyle.html
[INFO] Starting audit...
Audit done.
[INFO] You have 0 Checkstyle violations.
[INFO]
[INFO] --- maven-install-plugin:2.4:install (default-install) @ oscal-rest-service-parent ---
[INFO] Installing /home/degenaro/git/easy-dynamics/oscal-rest-service/pom.xml to /home/degenaro/.m2/repository/com/easydynamics/oscal-rest-service-parent/0.0.1-SNAPSHOT/oscal-rest-service-parent-0.0.1-SNAPSHOT.pom
[INFO]
[INFO] -----------< com.easydynamics:oscal-data-repository-commons >-----------
[INFO] Building oscal-data-repository-commons 0.0.1-SNAPSHOT [2/6]
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ oscal-data-repository-commons ---
[INFO] Deleting /home/degenaro/git/easy-dynamics/oscal-rest-service/oscal-data-repository-commons/target
[INFO]
[INFO] --- maven-checkstyle-plugin:3.1.2:check (validate) @ oscal-data-repository-commons ---
[WARNING] Old version of checkstyle detected. Consider updating to >= v8.30
[WARNING] For more information see: https://maven.apache.org/plugins/maven-checkstyle-plugin/examples/upgrading-checkstyle.html
[INFO] Starting audit...
Audit done.
[INFO] You have 0 Checkstyle violations.
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ oscal-data-repository-commons ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /home/degenaro/git/easy-dynamics/oscal-rest-service/oscal-data-repository-commons/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ oscal-data-repository-commons ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 10 source files to /home/degenaro/git/easy-dynamics/oscal-rest-service/oscal-data-repository-commons/target/classes
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] oscal-rest-service-parent 0.0.1-SNAPSHOT ........... SUCCESS [ 0.850 s]
[INFO] oscal-data-repository-commons ...................... FAILURE [ 0.492 s]
[INFO] oscal-data-repository-commons-tests ................ SKIPPED
[INFO] oscal-data-repository-file ......................... SKIPPED
[INFO] oscal-object-service ............................... SKIPPED
[INFO] oscal-rest-service-app 0.0.1-SNAPSHOT .............. SKIPPED
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.636 s
[INFO] Finished at: 2022-03-28T15:11:45-04:00
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project oscal-data-repository-commons: Fatal error compiling: invalid target release: 11 -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
[ERROR]
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR] mvn -rf :oscal-data-repository-commons
Currently with the upgrade of liboscal-java
to 1.0.1
(and its transitive dependency of metaschema-java
)the default behavior of ISerializer
has been changed to append rather than overwrite, which causes our file-persistent repository implementation to create unparsable JSON.
mvn clean install
See parent EasyDynamics/easygrc#4.
The local file path should be configurable via environment variables and a configurable mount/volume.
Currently the service will throw an error during a GET find all objects request if an object's persistence path contains non-json files. It should instead just skip the non-JSON content.
As seen on this workflow run, upgrading to version 4 of the delete-package-versions
action caused the publish
workflow fail.
We temporarily downgraded to version 3.0.1
to have the workflow pass. We either need to fix the workflow on our end or wait until a version is released that works.
Currently the service will throw an error during a GET find all objects request if an object's persistence path is misconfigured, i.e. doesn't exist. This should instead return an empty list if the folder simply doesn't exist, but should continue to throw an error for other misconfigurations, i.e. pointing to a file.
When using the OSCAL Editor UI to edit the parameters or description of a numbered control statement (eg. AC-1.2), the component-uuid
of the created by-component
object is not set, leaving the field blank.
Per the OSCAL Schema component-uuid
should be necessary for differentiating between descriptions pertaining to each component.
This affects edits to the statements
object under control-implementation
. See the OSCAL SSP Reference:
statements/by-components/component-uuid
is not being set.
When saving any changes via the REST Service, any date-time fields are filled with a format like:
2021-02-25T00:00:00.00-04:00
This causes a 500 error when trying to view in the OSCAL Viewer, presumably because that format is incorrect.
Setting the date manually to the format:
2021-02-25T00:00
instead seems to be the proper format.
As a user of a file-based implementation of the oscal-rest
API, I want to be able to resolve relative URLs within a JSON document/response, even if those requests are slightly out of compliance with the REST API so that I can also use other OSCAL tools directly on the files without having to go through the REST service implementation.
Consider an on-disk folder structure such as:
├── oscal-content
│ └── profiles
│ └── my-profile.json
│ └── resources
│ └── my-diagram.svg
│ └── system-security-plans
│ └── my-ssp.json
Let's assume that my-ssp.json
contains an import-profile
with a relativehref
of ../profiles/my-profiles.json
.
That relative URL will resolve for file-based tools, but if we look at the corresponding REST sequence, the GET
request for the SSP would be:
http://localhost:8080/oscal/v1/ssps/cff8385f-108e-40a5-8f7a-82f3dc0eaba8
so the browser will construct a relative URL request for the profile of:
http://localhost:8080/oscal/v1/ssps/cff8385f-108e-40a5-8f7a-82f3dc0eaba8/../../profiles/my-profile.json
which will then resolve to:
http://localhost:8080/oscal/v1/profiles/my-profile.json
and will currently fail at the service since my-profile.json
is not a UUID.
Similarly, the SSP might define a back-matter
resource with an rlink
href
of ../resources/my-diagram.svg
which would result in a constructed request URL of:
http://localhost:8080/oscal/v1/ssps/cff8385f-108e-40a5-8f7a-82f3dc0eaba8/../../resources/my-diagram.svg
which will then resolve to:
http://localhost:8080/oscal/v1/resources/my-diagram.svg
These resources
requests have not yet been defined by the oscal-rest
definition and is out of scope for this story, but will likely be added as part of the display of resources, i.e. EasyDynamics/easygrc#12 or EasyDynamics/oscal-react-library#225.
oscal-rest-service
accepts a file name as well as a UUID as an OSCAL object identifier in REST requests
http://localhost:8080/oscal/v1/profiles/my-profile.json
oscal-rest
path definitions have been consolidated, favoring the longer form, i.e. system-security-plans
over ssps
oscal-rest
and oscal-react-library
where those paths are definedA declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.