Preparing for Jira Software 10.0 and Jira Service Management 6.0 - multiple EAPs coming your way

Hi! If you have a dependency on jira-rest-plugin you have to migrate your plugin to RESTv2 for the imports to resolve correctly.
You can also consider making OSGi imports of your plugin mandatory instead of optional. It would make the system display clear error right at the bundle resolution stage (I suppose javax.ws.rs.* versions mismatch) instead of cryptic runtime ClassNotFounds.

1 Like

Hi! the rfc you linked refers to the platform level changes.
However, In products might override the visibility of certain libraries - hence the mismatches between platformā€™s RFC and Jiraā€™s changelog. Do you have a question or a suggestion about any specific lib?

Will it be continued to be supported in AMPS?
Or should we expect that half of local DC development routines might get broken in future Jira releases?

We will continue to support H2 in AMPS for now, but weā€™re for sure not going to break any local DC development environment. Most probably, we will replace H2 with Docker + different database engine (like PostgreSQL for example) in the future.

4 Likes

Please do not do this. Do not add this to AMPS. There is already the DC testing terraform solution available and it isnā€™t difficult to set up Docker-based development ourselves. This is not the DX improvement you are looking for.

To be honest @mkemp I personally donā€™t care about hot reload. Iā€™ve never tried implementing it. Iā€™m actually pretty happy with our current Docker-based DC development flow.

1 Like

On a side note, not entirely related to this topic: is there any plans for semi-/official docker images for arm64, at least for dev purposes?

Disagreed. Weā€™d appreciate it being in Amps. We really just run raw atlas-run commands without any deployment solution, so pushing us into Terraform today would be a huge hinderance to our roadmap.

2 Likes

AMPS is a maven-based solution (Atlassian Maven Plugin Suite). Adding docker execution from within Maven execution is going to be messy. If Atlassian wants to provide a docker-based solution to app development, it should be outside of the Maven process.

To be honest, I think the whole CLI should be rewritten and not be Maven-based. That way it could also start supporting other build tools (Ant, Gradle, etc). It is also taking on responsibilities it should not care about (like resource minification).

Oh well, maybe I should just write my own CLI.

4 Likes

I hear what youā€™re saying and I understand what you mean now, thanks. Appreciate you.

3 Likes

I agree, AMPS should not start executing docker commands. Whether it should or shouldnā€™t support other tools outside of Maven I leave to those that use other tools.

From the start I never used the AMPS CLI, I simply use the AMPS Maven plugin in my projects and use ā€œnormalā€ Maven commands to build my apps.

Having said this, if H2 is being removed, then AMPS should support, or at least make it easy, to ā€œimportā€ a database from another source, like docker. One thing that comes to mind is that AMPS should be able to populate an external DB just like it does now with H2. This would make it easy for dev to adopt it and not have to worry about going through the initial install process when starting an instance using AMPS.

1 Like

Hi There,

We are trying our plugin with jira 10 EAP, plugin not getting enabled and giving following error for SprintService class , Is there any change in that ?

failed; nested exception is java.lang.NoClassDefFoundError: com/atlassian/greenhopper/service/sprint/SprintService

Please guide me

If you havenā€™t upgraded your plugin to rest v2, start with that.

Iā€™ve encountered a similar issue, it was caused by constraint violation exception in bundle class loader due to conflict between imports from rest v1 and imports from JSW.

Setting log level for org.apache.felix.framework.BundleWiringImpl to DEBUG might help to troubleshoot.

Thanks for the reply, I will try that way.

Is this change included in EAP02, or should we wait for next one?

Iā€™m seeing this warning in log and failure to resolve the jackson package:
Package com.fasterxml.jackson.databind is internal and is not available for export to plugin xxx.xxx

1 Like

Thanks @lexek-92 for raising this. It looks like something gone wrong on our side. Weā€™ll have it investigated and fixed by next EAP.

Hello team; we wanted to inform you about features and changes we plan to include in upcoming Jira Software 10.0 / Jira Service Management 6.0 EAPs.

Deprecated code removals

Status: :construction: IN PROGRESS

The design of this feature hasnā€™t been finalised; please check back for more details.

We are planning to:

  • Remove deprecated Java methods and classes listed below:
Change Instructions
com.atlassian.jira.auditing.AssociatedItem Use com.atlassian.audit.entity.AuditResource instead
com.atlassian.jira.auditing.AuditingCategory Use com.atlassian.jira.auditing.AuditCategory instead
com.atlassian.jira.auditing.AuditingFilter Use com.atlassian.audit.api.AuditQuery instead
com.atlassian.jira.auditing.AuditingManager#countRecords Use com.atlassian.audit.api.AuditSearchService#count instead
com.atlassian.jira.auditing.AuditingManager#getRecords Use com.atlassian.audit.api.AuditSearchService#findBy or com.atlassian.audit.api.AuditSearchService#stream instead
com.atlassian.jira.auditing.AuditingManager#store Use com.atlassian.audit.api.AuditService#audit instead
com.atlassian.jira.auditing.AuditingService#getRecords Use com.atlassian.audit.api.AuditSearchService#findBy or com.atlassian.audit.api.AuditSearchService#stream instead
com.atlassian.jira.auditing.AuditingService#getTotalNumberOfRecords Use com.atlassian.audit.api.AuditSearchService#count instead
com.atlassian.jira.auditing.AuditingService#storeRecord Use com.atlassian.audit.api.AuditService#audit instead
com.atlassian.jira.auditing.AuditRecord Use com.atlassian.audit.entity.AuditEntity instead
com.atlassian.jira.auditing.ChangedValue Use com.atlassian.audit.entity.ChangedValue instead
com.atlassian.jira.auditing.RecordRequest Use com.atlassian.audit.entity.AuditEvent instead
com.atlassian.jira.auditing.Records.getRecords() Use #getResults instead
com.atlassian.jira.bc.customfield.CustomFieldDefinition.CustomFieldDefinition() Use a Builder to create the definition
com.atlassian.jira.bc.issue.comment.CommentService.CommentParameters.getGroupLevel() Use #getVisibility() instead
com.atlassian.jira.bc.issue.comment.CommentService.CommentParameters.getRoleLevelId() Use #getVisibility() instead
com.atlassian.jira.bc.issue.comment.CommentService.isGroupVisiblityEnabled() Use #isGroupVisibilityEnabled() instead
com.atlassian.jira.bc.issue.comment.CommentService.isProjectRoleVisiblityEnabled() Use #isProjectRoleVisibilityEnabled() instead
com.atlassian.jira.bc.issue.comment.CommentService.isValidCommentData(com.atlassian.jira.user.ApplicationUser, com.atlassian.jira.issue.Issue, java.lang.String, java.lang.String, com.atlassian.jira.util.ErrorCollection) Use #isValidCommentVisibility(ApplicationUser,Issue,com.atlassian.jira.bc.issue.visibility.Visibility,ErrorCollection) instead
com.atlassian.jira.bc.issue.util.VisibilityValidator.isGroupVisiblityEnabled() Use #isGroupVisibilityEnabled() instead
com.atlassian.jira.bc.issue.util.VisibilityValidator.isProjectRoleVisiblityEnabled() Use #isProjectRoleVisibilityEnabled() instead
com.atlassian.jira.bc.issue.worklog.WorklogInputParametersImpl.getGroupLevel() Use #getVisibility() instead
com.atlassian.jira.bc.issue.worklog.WorklogInputParametersImpl.getRoleLevelId() Use #getVisibility() instead
com.atlassian.jira.bc.license.JiraLicenseService.ValidationResult.getLicenseVersion() Use #getLicenseDetails().getLicenseVersion() instead
com.atlassian.jira.bc.license.JiraLicenseService.ValidationResult.getTotalUserCount() Use com.atlassian.jira.application.ApplicationAuthorizationService#getUserCount(ApplicationKey) or com.atlassian.jira.user.util.UserManager#getTotalUserCount() instead
com.atlassian.jira.bc.portal.PortalPageService.updatePortalPageUnconditionally(com.atlassian.jira.bc.JiraServiceContext, com.atlassian.jira.user.ApplicationUser, com.atlassian.jira.portal.PortalPage) Use #updatePortalPageOwner, #updatePortalPage, or PortalPageManager#update instead
com.atlassian.jira.bc.project.version.VersionService.validateReleaseDate(com.atlassian.jira.user.ApplicationUser, com.atlassian.jira.project.version.Version, java.lang.String) Use #validateUpdate(com.atlassian.jira.user.ApplicationUser,com.atlassian.jira.bc.project.version.VersionService.VersionBuilder) instead
com.atlassian.jira.bc.project.version.VersionService.validateVersionDetails(com.atlassian.jira.user.ApplicationUser, com.atlassian.jira.project.version.Version, java.lang.String, java.lang.String) Use #validateUpdate(com.atlassian.jira.user.ApplicationUser,com.atlassian.jira.bc.project.version.VersionService.VersionBuilder)
com.atlassian.jira.bc.user.UserService.validateRemoveUserFromApplication(com.atlassian.jira.user.ApplicationUser, com.atlassian.application.api.ApplicationKey) Use UserService#validateRemoveUserFromApplication(com.atlassian.jira.user.ApplicationUser,com.atlassian.jira.user.ApplicationUser,com.atlassian.application.api.ApplicationKey) instead
com.atlassian.jira.bc.whitelist.WhitelistService.getRules(com.atlassian.jira.bc.JiraServiceContext) Use com.atlassian.plugins.whitelist.WhitelistService#getAll() instead
com.atlassian.jira.bc.whitelist.WhitelistService.validateUpdateRules(com.atlassian.jira.bc.JiraServiceContext, java.util.List<java.lang.String>, boolean) Use com.atlassian.plugins.whitelist.WhitelistService#add(com.atlassian.plugins.whitelist.WhitelistRule), com.atlassian.plugins.whitelist.WhitelistService#remove(int), com.atlassian.plugins.whitelist.WhitelistService#disableWhitelist() and com.atlassian.plugins.whitelist.WhitelistService#enableWhitelist() instead
com.atlassian.jira.bulkedit.BulkOperationManager.getBulkOperations() Use #getProgressAwareBulkOperations() instead
com.atlassian.jira.bulkedit.operation.BulkMoveOperation.moveIssuesAndIndex(com.atlassian.jira.web.bean.BulkEditBean, com.atlassian.jira.user.ApplicationUser) Use #moveIssuesAndIndex(com.atlassian.jira.web.bean.BulkEditBean,com.atlassian.jira.user.ApplicationUser) instead
com.atlassian.jira.config.ConstantsManager.storeIssueTypes(java.util.List<org.ofbiz.core.entity.GenericValue>) Use #updateIssueType(String,String,Long,String,String,Long) or #recalculateIssueTypeSequencesAndStore(java.util.List) instead
com.atlassian.jira.config.properties.LookAndFeelBean.getVersion() Use #getSettingsHash() instead
com.atlassian.jira.config.properties.LookAndFeelBean.updateVersion(long) Use #updateSettingsHash() instead
com.atlassian.jira.config.SubTaskManager.insertSubTaskIssueType(java.lang.String, java.lang.Long, java.lang.String, java.lang.String) Use #insertSubTaskIssueType(String,Long,String,Long) instead
com.atlassian.jira.config.SubTaskManager.updateSubTaskIssueType(java.lang.String, java.lang.String, java.lang.Long, java.lang.String, java.lang.String) Use #updateSubTaskIssueType(String,String,Long,String,Long) instead
com.atlassian.jira.event.issue.IssueWatcherAddedEvent.getUser() Use #getApplicationUser() instead
com.atlassian.jira.event.issue.IssueWatcherDeletedEvent.getUser() Use #getApplicationUser() instead
com.atlassian.jira.event.mail.EmailQueueFlashedEvent Use EmailQueueFlushedEvent instead
com.atlassian.jira.help.HelpUrlsParser.defaultUrl(java.lang.String, java.lang.String) Use HelpUrlsParserBuilderFactory instead
com.atlassian.jira.help.HelpUrlsParser.onDemand(boolean) Use HelpUrlsParserBuilderFactory instead
com.atlassian.jira.imports.project.mapper.ProjectImportIdMapper.getValuesFromImport() Use getRegisteredOldIds() instead
com.atlassian.jira.imports.project.mapper.ProjectRoleActorMapper.getAllProjectRoleActors() Use the properly typed method #getProjectRoleActors() instead
com.atlassian.jira.issue.comments.CommentManager.getProjectRole(java.lang.Long) Use com.atlassian.jira.security.roles.ProjectRoleManager#getProjectRole(Long) instead
com.atlassian.jira.issue.customfields.CustomFieldType.getNonnullCustomFieldProvider() Use #getNonNullCustomFieldProvider() instead
com.atlassian.jira.issue.customfields.vdi.NonNullCustomFieldProvider.getCustomFieldInfo(com.atlassian.jira.issue.Issue) Use getCustomFieldInfo(List issues) instead
com.atlassian.jira.issue.fields.layout.field.FieldLayoutStorageException No replacement
com.atlassian.jira.issue.fields.rest.json.CommentBeanFactory.createRenderedBean(com.atlassian.jira.issue.comments.Comment) Use #createRenderedBean(com.atlassian.jira.issue.comments.Comment) instead
com.atlassian.jira.issue.index.ReindexAllCompletedEvent.shouldUpdateReplicatedIndex() Use #shouldNotifyCluster() instead
com.atlassian.jira.issue.index.ReindexAllStartedEvent.shouldUpdateReplicatedIndex() Use #shouldNotifyCluster() instead
com.atlassian.jira.issue.search.managers.IssueSearcherManager.getSearcherGroups(com.atlassian.jira.issue.search.SearchContext) Use #getSearcherGroups() instead
com.atlassian.jira.issue.search.managers.SearchHandlerManager.getSearcherGroups(com.atlassian.jira.issue.search.SearchContext) Use #getSearcherGroups()
com.atlassian.jira.issue.search.managers.SearchHandlerManager.getSearchersByClauseName(com.atlassian.jira.user.ApplicationUser, java.lang.String, com.atlassian.jira.issue.search.SearchContext) Use #getSearchersByClauseName(com.atlassian.crowd.embedded.api.User,String) instead
com.atlassian.jira.issue.search.searchers.util.IndexedInputHelper.getAllIndexValuesForMatchingClauses(com.atlassian.jira.user.ApplicationUser, com.atlassian.jira.issue.search.ClauseNames, com.atlassian.query.Query, com.atlassian.jira.issue.search.SearchContext) Use #getAllIndexValuesForMatchingClauses(com.atlassian.jira.user.ApplicationUser,com.atlassian.jira.issue.search.ClauseNames,com.atlassian.query.Query) instead
com.atlassian.jira.issue.search.searchers.util.IndexedInputHelper.getAllNavigatorValuesForMatchingClauses(com.atlassian.jira.user.ApplicationUser, com.atlassian.jira.issue.search.ClauseNames, com.atlassian.query.Query, com.atlassian.jira.issue.search.SearchContext) Use #getAllNavigatorValuesForMatchingClauses(ApplicationUser,com.atlassian.jira.issue.search.ClauseNames,com.atlassian.query.Query) instead
com.atlassian.jira.issue.util.IssueUpdateBean.getUser() Use #getApplicationUser() instead
com.atlassian.jira.jql.query.AbstractLocalDateOperatorQueryFactory Use com.atlassian.jira.jql.util.JqlLocalDateSupport#getLocalDatesFromQueryLiterals(java.util.List) instead
com.atlassian.jira.jql.util.JqlIssueSupport.getIssues(java.lang.String) Use #getIssue(String) instead
com.atlassian.jira.jql.util.JqlIssueSupport.getIssues(java.lang.String, com.atlassian.jira.user.ApplicationUser) Use #getIssue(String,com.atlassian.jira.user.ApplicationUser) instead
com.atlassian.jira.license.LicenseDetails.getLicenseStatusMessage(com.atlassian.jira.user.ApplicationUser, java.lang.String, com.atlassian.jira.user.util.UserManager) Use #getLicenseStatusMessage(com.atlassian.jira.util.I18nHelper,UserManager) instead
com.atlassian.jira.license.LicenseDetails.getLicenseStatusMessage(com.atlassian.jira.util.I18nHelper, com.atlassian.jira.web.util.OutlookDate, java.lang.String, com.atlassian.jira.user.util.UserManager) Use #getLicenseStatusMessage(com.atlassian.jira.util.I18nHelper,UserManager) instead
com.atlassian.jira.license.LicenseDetails.isLicenseAlmostExpired() Use LicenseDetails#getMaintenanceExpiryDate instead
com.atlassian.jira.mention.MentionService.sendCommentMentions(com.atlassian.jira.user.ApplicationUser, java.util.Set<com.atlassian.jira.notification.NotificationRecipient>, com.atlassian.jira.issue.comments.Comment, com.atlassian.jira.issue.comments.Comment) Use #sendCommentMentions(Set,ApplicationUser,Comment,Comment) instead
com.atlassian.jira.mention.MentionService.sendIssueCreateMentions(com.atlassian.jira.user.ApplicationUser, java.util.Set<com.atlassian.jira.notification.NotificationRecipient>, com.atlassian.jira.issue.Issue) Use #sendIssueCreateMentions(Set,ApplicationUser,Issue) instead
com.atlassian.jira.mention.MentionService.sendIssueEditMentions(com.atlassian.jira.user.ApplicationUser, java.util.Set<com.atlassian.jira.notification.NotificationRecipient>, com.atlassian.jira.issue.Issue, com.atlassian.jira.issue.comments.Comment) Use #sendIssueEditMentions(Set,ApplicationUser,Issue,Comment) instead
com.atlassian.jira.permission.PermissionSchemeManager.getEntitiesByType(org.ofbiz.core.entity.GenericValue, com.atlassian.jira.security.plugin.ProjectPermissionKey, java.lang.String) Use #getPermissionSchemeEntries(long,com.atlassian.jira.security.plugin.ProjectPermissionKey,String) instead
com.atlassian.jira.permission.PermissionSchemeManager.getGroups(java.lang.Long, com.atlassian.jira.project.Project) Use #getGroups(ProjectPermissionKey,Project) instead
com.atlassian.jira.plugin.keyboardshortcut.KeyboardShortcutManager.getActiveShortcuts() Use #listActiveShortcutsUniquePerContext instead
com.atlassian.jira.plugin.webfragment.conditions.AbstractJiraPermissionCondition Use AbstractPermissionCondition instead.
com.atlassian.jira.plugin.webfragment.conditions.AbstractPermissionCondition Use AbstractProjectPermissionCondition instead.
com.atlassian.jira.project.type.ProjectTypesEnabledCondition No replacement
com.atlassian.jira.scheme.SchemeManager.createScheme(java.lang.String, java.lang.String) Use #createSchemeObject(String,String) instead.
com.atlassian.jira.scheme.SchemeManager.getGroups(java.lang.Long, org.ofbiz.core.entity.GenericValue) Use #getGroups(Long,com.atlassian.jira.project.Project) instead
com.atlassian.jira.security.GlobalPermissionEntry.getGlobalPermissionType() Use #getPermissionKey() instead
com.atlassian.jira.security.JiraAuthenticationContext.getI18nBean() Use #getI18nHelper() instead
com.atlassian.jira.security.JiraAuthenticationContext.getText(java.lang.String) Use getText() method on #getI18nHelper() instead
com.atlassian.jira.sharing.ShareManager.hasPermission(com.atlassian.jira.user.ApplicationUser, com.atlassian.jira.sharing.SharedEntity) Use #isSharedWith(com.atlassian.crowd.embedded.api.User,SharedEntity) instead
com.atlassian.jira.user.preferences.JiraUserPreferences.JiraUserPreferences() You should not construct user preferences directly Request them through the UserPreferencesManager instead
com.atlassian.jira.util.collect.MapBuilder.toFastMap() Use ImmutableMap directly instead
com.atlassian.jira.util.collect.MapBuilder.toImmutableMap() Use #toMap() instead, or consider using ImmutableMap if the map does not need to accept nulls
com.atlassian.jira.util.index.Contexts.nullContext() Use #com.atlassian.jira.task.context.Contexts#nullContext() instead
com.atlassian.jira.util.JiraDurationUtils.onClearCache(com.atlassian.jira.event.ClearCacheEvent) Use #DurationFormatChanged instead
com.atlassian.jira.util.JiraDurationUtils.start() No replacement
com.atlassian.jira.web.action.issue.IssueCreationHelperBean.getProvidedFieldNames(com.atlassian.jira.user.ApplicationUser, com.atlassian.jira.issue.Issue) Use #getProvidedFieldNames(com.atlassian.jira.issue.Issue) instead
com.atlassian.jira.web.bean.MultiBulkMoveBean.setTargetProject(org.ofbiz.core.entity.GenericValue) Use #setTargetProject(com.atlassian.jira.project.Project) instead
com.atlassian.jira.web.util.HelpUtil.HelpPath.getSimpleUrl() Use #getUrl() instead
com.atlassian.jira.web.util.OutlookDate.format() Use #com.atlassian.jira.datetime.DateTimeFormatter#format(java.util.Date) instead
com.atlassian.jira.web.util.OutlookDate.getCompleteDateFormat() Use #com.atlassian.jira.datetime.DateTimeFormatter#getFormatHint() instead
com.atlassian.jira.web.util.OutlookDate.getDatePickerFormat() Use #com.atlassian.jira.datetime.DateTimeFormatter#getFormatHint() instead
com.atlassian.jira.web.util.OutlookDate.getDateTimePickerFormat() Use #com.atlassian.jira.datetime.DateTimeFormatter#getFormatHint() instead
com.atlassian.jira.web.util.OutlookDate.getNow() Use java.util.Date#Date() instead
  • Remove deprecated REST endpoints listed below:
Change Instructions
Public endpoint GET /rest/api/2/group provided by com.atlassian.jira.rest.v2.issue.GroupResource#getGroup removed Use GET /rest/api/2/group/member provided by com.atlassian.jira.rest.v2.issue.GroupResource#getUsersFromGroup
Public endpoint DELETE /rest/api/2/version/{id} provided by com.atlassian.jira.rest.v2.issue.VersionResource#delete(java.lang.String, java.lang.String, java.lang.String) removed Use POST /rest/api/2/version/{id}/removeAndSwap provided by com.atlassian.jira.rest.v2.issue.VersionResource#delete(String, DeleteAndReplaceVersionBean)
Public endpoint GET /rest/api/2/auditing/record provided by com.atlassian.jira.rest.v2.admin.auditing.AuditingResource#getRecords removed
Public endpoint POST /rest/api/2/auditing/record provided by com.atlassian.jira.rest.v2.admin.auditing.AuditingResource#addRecord removed
  • Clean up a set of feature flags:
  * jira.quick.search
  * com.atlassian.jira.custom.csv.escaper
  * atlassian.cdn.static.assets
  * com.atlassian.jira.agile.darkfeature.burnupchart
  * jira.users.and.roles.page.in.react
  * optimistic.transitions
  * com.atlassian.jira.advanced.audit.log
  * velocity.chart.ui

See also API policy for Java APIs

No actions are required for this change.

Endpoint default security annotations

Status: :construction: IN PROGRESS

The design of this feature hasnā€™t been finalised; please check back for more details.

Our latest update will introduce changes for improved endpoint security where you can better control endpoint access with new annotations. Critical annotations to review are AdminOnly, AnonymousSiteAccess, LicensedOnly, SystemAdminOnly, UnlicensedSiteAccess, and UnrestrictedAccess. Theyā€™ve been revised to ensure only the intended users access your application endpoints. Starting from Jira Software 10.0 / Jira Service Management 6.0, only licensed users can access resources without specified annotations of access criteria.

Discover the full details of this change on https://developer.atlassian.com/platform/marketplace/dc-apps-platform-7-preparing-for-secure-endpoints/

Allowlist your Velocity template class and method invocations

Status: :construction: IN PROGRESS

The design of this feature hasnā€™t been finalised; please check back for more details.

Like Confluence 9.0, starting from Jira Software 10.0 / Jira Service Management 6.0, we plan to migrate the method invocations in Velocity templates to an allowlist approach. All method invocations within a Velocity template will be explicitly allowed using a newly introduced annotation or app module descriptor.

Below are the allowed classes and methods:

introspector.allowlist.classes = java.io.Serializable,\
java.io.ObjectInputValidation,\
java.lang.reflect.Proxy,\
net.sf.hibernate.proxy.HibernateProxy,\
org.springframework.cglib.proxy.Factory
introspector.allowlist.methods = getEditVM,\
removeHtmlTags,\
htmlEncode,\
escapeHtml,\
getLabelSearchPath,\
encodeHtml,\
encodeForHtml

Additionally, all method invocations will be subject to a ā€œdepthā€ limit, preventing context items from being traversed/chained indefinitely.

$contextItem.firstInvocation.secondInvocation.thirdInvocation

Allowlist your Velocity files on the filesystem

Status: :construction: IN PROGRESS

The design of this feature has yet to be finalized; please check back for further details.

We are making steps towards verifiably secure installation directories for all Data Centre products. This change not only increases the difficulty for an attacker to exploit filesystem access, but also allows customers to verify the state of the product installation.

From Bamboo 10.0, Bitbucket 9.0, Confluence 9.0, Crowd 6.0, Jira Software 10.0, and Jira Service Management 6.0, all Velocity files stored on the filesystem (e.g., shared, local home, or any other) will need to be explicitly allowlisted. Files stored inside of .jar files and bundled within plugins will not be affected.

In Confluence, Jira Software, and Jira Service Management, itā€™s possible to update the Velocity engine configuration to add files to the allowlist. This must be repeated for each new engine instance. This property is cached when the engine starts, enhancing performance and making it more difficult for attackers to disable.

velocity.addProperty(Velocity.RESOURCE_FILE_ALLOWLIST, "relative/file/path.vm")

Allowlist your Velocity filetypes for files on the filesystem

Status: :construction: IN PROGRESS

The design of this feature has yet to be finalized; please check back for further details.

We are making steps towards verifiably secure installation directories for all Data Centre products. This change not only increases the difficulty for an attacker to exploit filesystem access, but also allows customers to verify the state of the product installation.

From Bamboo 10.0, Bitbucket 9.0, Confluence 9.0, Crowd 6.0, and Jira Software 10.0, and Jira Service Management 6.0 onwards, all Velocity files stored on the filesystem (e.g., shared, local home, or any other) must be of a specific filetype. Files stored inside of .jar files and bundled within plugins will not be affected.

In Confluence, Jira Software, and Jira Service Management, itā€™s possible to update the Velocity engine configuration for the specific ResourceLoader to add the filetypes to the allowlist. This must be repeated for each new engine instance. This property is cached when the engine starts, enhancing performance and making it more difficult for attackers to disable.

velocity.addProperty(Velocity.CLASSPATH_RESOURCE_FILETYPE_ALLOWLIST, ".vm,.vtl")
velocity.addProperty(Velocity.FILE_RESOURCE_FILETYPE_ALLOWLIST, ".vm,.vtl")

Disabling runtime JSP compilation

Status: :construction: IN PROGRESS

The design of this feature has yet to be finalized; please check back for further details.

Starting with Jira Software 10.0, and Jira Service Management 6.0 JSP runtime compilation is disabled. JSP files added to the Tomcat directory that are not shipped with the product will not be served. Furthermore, modifications to the JSP files will not be reflected. Please use Soy or Velocity templates instead.

Looking forward to hearing your feedback. Cheers.
The Jira team

3 Likes

:red_circle: When starting the Jira 10.0.0 EAP02 docker image I get this error and startup fails

  • :one: Image: 10.0.0-EAP02-ubuntu-jdk11:
2024-04-14 19:19:45,749+0000 JIRA-Bootstrap ERROR      [c.a.jira.upgrade.PluginSystemLauncher] A fatal error occured during initialisation. JIRA has been locked.
com.atlassian.jira.InfrastructureException: Error occurred while starting component 'com.atlassian.jira.instrumentation.Instrumentation'.
	at com.atlassian.jira.component.pico.ComponentManager.startStartableComponents(ComponentManager.java:348)
	at com.atlassian.jira.component.pico.ComponentManager.earlyStartPluginSystem(ComponentManager.java:259)
	at com.atlassian.jira.upgrade.PluginSystemLauncher.start(PluginSystemLauncher.java:48)
	at com.atlassian.jira.startup.DefaultJiraLauncher.lambda$postDbLaunch$2(DefaultJiraLauncher.java:151)
	at com.atlassian.jira.config.database.DatabaseConfigurationManagerImpl.doNowOrEnqueue(DatabaseConfigurationManagerImpl.java:305)
	at com.atlassian.jira.config.database.DatabaseConfigurationManagerImpl.doNowOrWhenDatabaseActivated(DatabaseConfigurationManagerImpl.java:202)
	at com.atlassian.jira.startup.DefaultJiraLauncher.postDbLaunch(DefaultJiraLauncher.java:142)
	at com.atlassian.jira.startup.DefaultJiraLauncher.lambda$start$0(DefaultJiraLauncher.java:108)
	at com.atlassian.jira.util.devspeed.JiraDevSpeedTimer.run(JiraDevSpeedTimer.java:31)
	at com.atlassian.jira.startup.DefaultJiraLauncher.start(DefaultJiraLauncher.java:106)
	at com.atlassian.jira.startup.LauncherContextListener.initSlowStuff(LauncherContextListener.java:154)
	at java.base/java.lang.Thread.run(Thread.java:829)
Caused by: com.atlassian.cache.CacheException: com.atlassian.extras.common.LicenseException: java.lang.RuntimeException: Signature verification failed
	at com.atlassian.cache.memory.DelegatingCachedReference.get(DelegatingCachedReference.java:92)
	at com.atlassian.cache.impl.metrics.InstrumentedCachedReference.get(InstrumentedCachedReference.java:58)
	at com.atlassian.jira.cache.stats.CachedReferenceWithStats.get(CachedReferenceWithStats.java:24)
	at com.atlassian.jira.license.JiraLicenseManagerImpl.getLicenses(JiraLicenseManagerImpl.java:100)
	at com.atlassian.jira.license.JiraLicenseManagerImpl.getLicenses(JiraLicenseManagerImpl.java:51)
	at com.atlassian.jira.instrumentation.external.InternalStatisticsExternalGauges$1.<init>(InternalStatisticsExternalGauges.java:92)
	at com.atlassian.jira.instrumentation.external.InternalStatisticsExternalGauges.registerLicenceInstruments(InternalStatisticsExternalGauges.java:91)
	at com.atlassian.jira.instrumentation.external.InternalStatisticsExternalGauges.<init>(InternalStatisticsExternalGauges.java:84)
	at com.atlassian.jira.instrumentation.external.ExternalGauges.installInstruments(ExternalGauges.java:26)
	at com.atlassian.jira.instrumentation.Instrumentation.start(Instrumentation.java:151)
	at com.atlassian.jira.component.pico.ComponentManager.startStartableComponents(ComponentManager.java:344)
	... 11 more
Caused by: com.atlassian.extras.common.LicenseException: java.lang.RuntimeException: Signature verification failed
	at com.atlassian.extras.decoder.v2.Version2LicenseDecoder.checkAndGetLicenseText(Version2LicenseDecoder.java:217)
	at com.atlassian.extras.decoder.v2.Version2LicenseDecoder.doDecode(Version2LicenseDecoder.java:114)
	at com.atlassian.extras.decoder.api.AbstractLicenseDecoder.decode(AbstractLicenseDecoder.java:15)
	at com.atlassian.extras.decoder.api.DelegatingLicenseDecoder.decode(DelegatingLicenseDecoder.java:30)
	at com.atlassian.extras.core.DefaultLicenseManager.decodeLicense(DefaultLicenseManager.java:62)
	at com.atlassian.extras.core.DefaultLicenseManager.getAtlassianLicense(DefaultLicenseManager.java:50)
	at com.atlassian.extras.core.DefaultLicenseManager.getLicense(DefaultLicenseManager.java:39)
	at com.atlassian.jira.license.LicenseDetailsFactoryImpl$JiraProductLicenseManager.getProductLicense(LicenseDetailsFactoryImpl.java:132)
	at com.atlassian.jira.license.LicenseDetailsFactoryImpl.getLicense(LicenseDetailsFactoryImpl.java:70)
	at com.google.common.collect.Iterators$6.transform(Iterators.java:829)
	at com.google.common.collect.TransformedIterator.next(TransformedIterator.java:52)
	at com.atlassian.jira.license.JiraLicenseManagerImpl$CachedLicenses.<init>(JiraLicenseManagerImpl.java:404)
	at com.atlassian.jira.license.JiraLicenseManagerImpl$CachedLicenses.<init>(JiraLicenseManagerImpl.java:392)
	at com.atlassian.jira.license.JiraLicenseManagerImpl.loadLicenses(JiraLicenseManagerImpl.java:389)
	at com.atlassian.cache.memory.MemoryCacheManager$1.load(MemoryCacheManager.java:130)
	at com.atlassian.cache.memory.MemoryCacheManager$1.load(MemoryCacheManager.java:106)
	at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3576)
	at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2318)
	at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2191)
	at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2081)
	at com.google.common.cache.LocalCache.get(LocalCache.java:4019)
	at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:4042)
	at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:5024)
	at com.google.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:5031)
	at com.atlassian.cache.memory.DelegatingCachedReference.getUnderLock(DelegatingCachedReference.java:102)
	at com.atlassian.cache.memory.DelegatingCachedReference.get(DelegatingCachedReference.java:87)
	... 21 more
Caused by: java.lang.RuntimeException: Signature verification failed
	at com.atlassian.extras.keymanager.KeyManager.verify(KeyManager.java:141)
	at com.atlassian.extras.decoder.v2.Version2LicenseDecoder.checkAndGetLicenseText(Version2LicenseDecoder.java:212)
	... 46 more
Caused by: java.security.SignatureException: Invalid encoding for signature
	at java.base/sun.security.provider.DSA.engineVerify(DSA.java:346)
	at java.base/sun.security.provider.DSA.engineVerify(DSA.java:292)
	at java.base/java.security.Signature$Delegate.engineVerify(Signature.java:1416)
	at java.base/java.security.Signature.verify(Signature.java:790)
	at com.atlassian.extras.keymanager.KeyManager.verify(KeyManager.java:139)
	... 47 more
Caused by: java.io.IOException: Sequence tag error
	at java.base/sun.security.util.DerInputStream.getSequence(DerInputStream.java:322)
	at java.base/sun.security.provider.DSA.engineVerify(DSA.java:336)
	... 51 more

Actually this will be changed a bit:
DELETE /rest/api/2/version/{id} will be changed to get the semantics of POST /rest/api/2/version/{id}/removeAndSwap while the latter will become deprecated

@AndrzejKotas : Could we please have an official documentation page instead of keep posting on a message thread?